var contexts = require(“./contexts”),

Parser = require('./parser/parser'),
FunctionImporter = require('./plugins/function-importer');

module.exports = function(environment) {

// FileInfo = {
//  'relativeUrls' - option - whether to adjust URL's to be relative
//  'filename' - full resolved filename of current file
//  'rootpath' - path to append to normal URLs for this node
//  'currentDirectory' - path to the current file, absolute
//  'rootFilename' - filename of the base file
//  'entryPath' - absolute path to the entry file
//  'reference' - whether the file should not be output and only output parts that are referenced

var ImportManager = function(context, rootFileInfo) {
    this.rootFilename = rootFileInfo.filename;
    this.paths = context.paths || [];  // Search paths, when importing
    this.contents = {};             // map - filename to contents of all the files
    this.contentsIgnoredChars = {}; // map - filename to lines at the beginning of each file to ignore
    this.mime = context.mime;
    this.error = null;
    this.context = context;
    // Deprecated? Unused outside of here, could be useful.
    this.queue = [];        // Files which haven't been imported yet
    this.files = {};        // Holds the imported parse trees.
};
/**
 * Add an import to be imported
 * @param path - the raw path
 * @param tryAppendLessExtension - whether to try appending the less extension (if the path has no extension)
 * @param currentFileInfo - the current file info (used for instance to work out relative paths)
 * @param importOptions - import options
 * @param callback - callback for when it is imported
 */
ImportManager.prototype.push = function (path, tryAppendLessExtension, currentFileInfo, importOptions, callback) {
    var importManager = this;
    this.queue.push(path);

    var fileParsedFunc = function (e, root, fullPath) {
        importManager.queue.splice(importManager.queue.indexOf(path), 1); // Remove the path from the queue

        var importedEqualsRoot = fullPath === importManager.rootFilename;
        if (importOptions.optional && e) {
            callback(null, {rules:[]}, false, null);
        }
        else {
            importManager.files[fullPath] = root;
            if (e && !importManager.error) { importManager.error = e; }
            callback(e, root, importedEqualsRoot, fullPath);
        }
    };

    var newFileInfo = {
        relativeUrls: this.context.relativeUrls,
        entryPath: currentFileInfo.entryPath,
        rootpath: currentFileInfo.rootpath,
        rootFilename: currentFileInfo.rootFilename
    };

    var fileManager = environment.getFileManager(path, currentFileInfo.currentDirectory, this.context, environment);

    if (!fileManager) {
        fileParsedFunc({ message: "Could not find a file-manager for " + path });
        return;
    }

    if (tryAppendLessExtension) {
        path = fileManager.tryAppendExtension(path, importOptions.plugin ? ".js" : ".less");
    }

    var loadFileCallback = function(loadedFile) {
        var resolvedFilename = loadedFile.filename,
            contents = loadedFile.contents.replace(/^\uFEFF/, '');

        // Pass on an updated rootpath if path of imported file is relative and file
        // is in a (sub|sup) directory
        //
        // Examples:
        // - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/',
        //   then rootpath should become 'less/module/nav/'
        // - If path of imported file is '../mixins.less' and rootpath is 'less/',
        //   then rootpath should become 'less/../'
        newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
        if (newFileInfo.relativeUrls) {
            newFileInfo.rootpath = fileManager.join(
                (importManager.context.rootpath || ""),
                fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));

            if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) {
                newFileInfo.rootpath = fileManager.join(newFileInfo.entryPath, newFileInfo.rootpath);
            }
        }
        newFileInfo.filename = resolvedFilename;

        var newEnv = new contexts.Parse(importManager.context);

        newEnv.processImports = false;
        importManager.contents[resolvedFilename] = contents;

        if (currentFileInfo.reference || importOptions.reference) {
            newFileInfo.reference = true;
        }

        if (importOptions.plugin) {
            new FunctionImporter(newEnv, newFileInfo).eval(contents, function (e, root) {
                fileParsedFunc(e, root, resolvedFilename);
            });
        } else if (importOptions.inline) {
            fileParsedFunc(null, contents, resolvedFilename);
        } else {
            new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) {
                fileParsedFunc(e, root, resolvedFilename);
            });
        }
    };

    var promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, this.context, environment,
        function(err, loadedFile) {
        if (err) {
            fileParsedFunc(err);
        } else {
            loadFileCallback(loadedFile);
        }
    });
    if (promise) {
        promise.then(loadFileCallback, fileParsedFunc);
    }
};
return ImportManager;

};