class PathResolver {

    @SuppressWarnings("IndexOfReplaceableByContains")
    public static List<File> resolvePath(File incPath, File cwd) {
        if(cwd == null)
            cwd = new File(Config.getHomeDir());

        //if incPath start with eg: ./, remove it
        if(incPath.toString().startsWith(CURRENT_WITH_SEPARATOR)) {
            incPath = new File(incPath.toString().substring(CURRENT_WITH_SEPARATOR.length()));
        }

        if(incPath.toString().startsWith(TILDE_WITH_SEPARATOR)) {
            if(Config.getHomeDir().endsWith(Config.getPathSeparator()))
                incPath = new File(Config.getHomeDir()+incPath.toString().substring(2));
            else
                incPath = new File(Config.getHomeDir()+incPath.toString().substring(1));
        }

        if(incPath.toString().indexOf(TILDE) == 0) {
            if(incPath.toString().length() > 1) {
                // directories which name starts with tilde
                incPath = new File(cwd.toString() + Config.getPathSeparator() + incPath.toString());
            } else {
                incPath = new File(Config.getHomeDir());
            }
        }

        //  foo1/./foo2 is changed to foo1/foo2
        if(incPath.toString().indexOf(SEPARATOR_CURRENT_SEPARATOR) > -1) {
            int index = incPath.toString().indexOf(SEPARATOR_CURRENT_SEPARATOR);
            if(index == 0) {
                incPath = new File(incPath.toString().substring(SEPARATOR_CURRENT_SEPARATOR.length()-1));
            }
            else {
                incPath = new File(incPath.toString().substring(0, index) +
                        incPath.toString().substring(index+2, incPath.toString().length()));
            }
        }

        //parentPath do not start with / or by a windows driver letter and cwd is not / either
        if( incPath.toString().indexOf(ROOT) != 0 && incPath.toString().indexOf(DRIVER_SEPARATOR) == -1 && !cwd.toString().equals(ROOT)) {
            if(cwd.toString().endsWith(Config.getPathSeparator()))
                incPath = new File(cwd.toString() + incPath.toString());
            else
                incPath = new File(cwd.toString() + Config.getPathSeparator() + incPath.toString());
        }

        if(incPath.toString().indexOf(PARENT_WITH_SEPARATOR) > -1) {
            String tmp = incPath.toString();
            while(tmp.indexOf(PARENT_WITH_SEPARATOR) > -1) {
                int index = tmp.indexOf(PARENT_WITH_SEPARATOR);
                if(index == 0) {
                    tmp = tmp.substring(PARENT_WITH_SEPARATOR.length());
                }
                else {
                    File tmpFile = new File(tmp.substring(0, index));
                    tmpFile = tmpFile.getParentFile();
                    if(tmpFile == null)
                        tmpFile = new File(Config.getPathSeparator());
                    tmpFile = new File(tmpFile.toString() + tmp.substring(index+ PARENT_WITH_SEPARATOR.length()-1));
                    //tmp = tmp.substring(0, index) + tmp.substring(index+PARENT_WITH_SEPARATOR.length());
                    tmp = tmpFile.toString();
                }
            }
            incPath = new File(tmp);
        }

        if(incPath.toString().endsWith(PARENT)) {
            incPath = new File(incPath.toString().substring(0, incPath.toString().length()-PARENT.length()));
            incPath = incPath.getParentFile();
            if(incPath == null)
                incPath = new File(Config.getPathSeparator());
        }

        if( incPath.toString().indexOf(STAR) > -1 || incPath.toString().indexOf(WILDCARD) > -1) {
            PathCriteria pathCriteria = parsePath(incPath);
            if(incPath.toString().indexOf(SEPARATOR) > -1) {
                List<File> foundFiles  = null;
                if(pathCriteria.getCriteria().equals(String.valueOf(STAR))) {
                    foundFiles = new ArrayList<>();
                    foundFiles.add(new File(pathCriteria.getParentPath()));
                }
                else
                    foundFiles = findFiles(new File(pathCriteria.parentPath), pathCriteria.getCriteria(), false);
                if(pathCriteria.childPath.length() == 0)
                    return foundFiles;
                else {
                    List<File> outFiles = new ArrayList<>();
                    for(File f : foundFiles)
                        if(new File(f+Config.getPathSeparator()+pathCriteria.childPath).exists())
                            outFiles.add(new File(f+Config.getPathSeparator()+pathCriteria.childPath));

                    return outFiles;
                }
            }
            //just wildcard without separators
            else {
                if(incPath.toString().length() == 1) {
                    List<File> foundFiles = findFiles(new File(pathCriteria.parentPath), pathCriteria.getCriteria(), false);
                    if(pathCriteria.childPath.length() == 0)
                        return foundFiles;
                }

                return new ArrayList<File>();
            }
        }
        else {
            //no wildcards
            ArrayList<File> fileList = new ArrayList<>(1);
            fileList.add(incPath);
            return fileList;
        }
    }

}