(function (tree) {
//
// CSS @import node
//
// The general strategy here is that we don't want to wait
// for the parsing to be completed, before we start importing
// the file. That's because in the context of a browser,
// most of the time will be spent waiting for the server to respond.
//
// On creation, we push the import path to our import queue, though
// `import,push`, we also pass it a callback, which it'll call once
// the file has been fetched, and parsed.
//
tree.Import = function (path, features, options, index, currentFileInfo) {
    this.options = options;
    this.index = index;
    this.path = path;
    this.features = features;
    this.currentFileInfo = currentFileInfo;

    if (this.options.less !== undefined || this.options.inline) {
        this.css = !this.options.less || this.options.inline;
    } else {
        var pathValue = this.getPath();
        if (pathValue && /css([\?;].*)?$/.test(pathValue)) {
            this.css = true;
        }
    }
};

//
// The actual import node doesn't return anything, when converted to CSS.
// The reason is that it's used at the evaluation stage, so that the rules
// it imports can be treated like any other rules.
//
// In `eval`, we make sure all Import nodes get evaluated, recursively, so
// we end up with a flat structure, which can easily be imported in the parent
// ruleset.
//
tree.Import.prototype = {
    type: "Import",
    accept: function (visitor) {
        if (this.features) {
            this.features = visitor.visit(this.features);
        }
        this.path = visitor.visit(this.path);
        if (!this.options.inline && this.root) {
            this.root = visitor.visit(this.root);
        }
    },
    genCSS: function (env, output) {
        if (this.css) {
            output.add("@import ", this.currentFileInfo, this.index);
            this.path.genCSS(env, output);
            if (this.features) {
                output.add(" ");
                this.features.genCSS(env, output);
            }
            output.add(';');
        }
    },
    toCSS: tree.toCSS,
    getPath: function () {
        if (this.path instanceof tree.Quoted) {
            var path = this.path.value;
            return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less';
        } else if (this.path instanceof tree.URL) {
            return this.path.value.value;
        }
        return null;
    },
    evalForImport: function (env) {
        return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo);
    },
    evalPath: function (env) {
        var path = this.path.eval(env);
        var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;

        if (!(path instanceof tree.URL)) {
            if (rootpath) {
                var pathValue = path.value;
                // Add the base path if the import is relative
                if (pathValue && env.isPathRelative(pathValue)) {
                    path.value = rootpath +pathValue;
                }
            }
            path.value = env.normalizePath(path.value);
        }

        return path;
    },
    eval: function (env) {
        var ruleset, features = this.features && this.features.eval(env);

        if (this.skip) {
            if (typeof this.skip === "function") {
                this.skip = this.skip();
            }
            if (this.skip) {
                return []; 
            }
        }
         
        if (this.options.inline) {
            //todo needs to reference css file not import
            var contents = new(tree.Anonymous)(this.root, 0, {filename: this.importedFilename}, true, true);
            return this.features ? new(tree.Media)([contents], this.features.value) : [contents];
        } else if (this.css) {
            var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index);
            if (!newImport.css && this.error) {
                throw this.error;
            }
            return newImport;
        } else {
            ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0));

            ruleset.evalImports(env);

            return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules;
        }
    }
};

})(require('../tree'));
