'use strict';

var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var glob = require('glob');
var parseImports = require('./parse-imports');

// resolve a sass module to a path
function resolveSassPath(sassPath, loadPaths) {
  // trim any file extensions
  var sassPathName = sassPath.replace(/\.\w+$/, '');
  // check all load paths
  for(var p in loadPaths) {
    var scssPath = path.normalize(loadPaths[p] + "/" + sassPathName + ".scss");
    if (fs.existsSync(scssPath)) {
      return scssPath;
    }
    // special case for _partials
    var partialPath = path.join(path.dirname(scssPath), "_" + path.basename(scssPath));
    if (fs.existsSync(partialPath)) {
      return partialPath
    }
  }
  var errMsg = "File to import not found or unreadable: " + sassPath;
  throw errMsg;
}

function Graph(loadPaths, dir) {
  this.dir = dir;
  this.loadPaths = loadPaths;
  this.index = {};

  if(dir) {
    var graph = this;
    _(glob.sync(dir+"/**/*.scss", {})).forEach(function(file) {
      graph.addFile(path.resolve(file));
    });
  }
}

// add a sass file to the graph
Graph.prototype.addFile = function(filepath, parent) {
  var entry = this.index[filepath] = this.index[filepath] || {
    imports: [],
    importedBy: [],
    modified: fs.statSync(filepath).mtime
  };

  var imports = parseImports(fs.readFileSync(filepath, 'utf-8'));
  var cwd = path.dirname(filepath)

  for (var i in imports) {
    [this.dir, cwd].forEach(function (path) {
      if (path) {
        this.loadPaths.push(path);
      }
    }.bind(this));
    var resolved = resolveSassPath(imports[i], _.uniq(this.loadPaths));
    if (!resolved) return false;

    // recurse into dependencies if not already enumerated
    if(!_.contains(entry.imports, resolved)) {
      entry.imports.push(resolved);
      this.addFile(resolved, filepath);
    }
  }

  // add link back to parent
  if(parent != null) {
    entry.importedBy.push(parent);
  }
};

// visits all files that are ancestors of the provided file
Graph.prototype.visitAncestors = function(filepath, callback) {
  this.visit(filepath, callback, function(node) {
    return node.importedBy;
  });
};

// visits all files that are descendents of the provided file
Graph.prototype.visitDescendents = function(filepath, callback) {
  this.visit(filepath, callback, function(node) {
    return node.imports;
  });
};

// a generic visitor that uses an edgeCallback to find the edges to traverse for a node
Graph.prototype.visit = function(filepath, callback, edgeCallback, visited) {
  var visited = visited || [];
  if(!this.index.hasOwnProperty(filepath)) {
    throw "Graph doesn't contain "+filepath;
  }
  var edges = edgeCallback(this.index[filepath]);
  for(var i in edges) {
    if(!_.contains(visited, edges[i])) {
      visited.push(edges[i]);
      callback(edges[i], this.index[edges[i]]);
      this.visit(edges[i], callback, edgeCallback, visited);
    }
  }
};

function processOptions(options) {
  options = options || {};
  if(!options.hasOwnProperty('loadPaths')) options['loadPaths'] = [];
  return options;
}

module.exports.parseFile = function(filepath, options) {
  var filepath = path.resolve(filepath);
  var options = processOptions(options);
  var graph = new Graph(options.loadPaths);
  graph.addFile(filepath);
  return graph;
};

module.exports.parseDir = function(dirpath, options) {
  var dirpath = path.resolve(dirpath);
  var options = processOptions(options);
  var graph = new Graph(options.loadPaths, dirpath);
  return graph;
};

@@ -1301,16 +1301,38 @@
 e%0A  %7D;%0A%0A
+  var resolvedParent;%0A
   var im
@@ -1423,16 +1423,17 @@
 ilepath)
+;
 %0A%0A  for 
@@ -1509,24 +1509,63 @@
     if (path
+ && this.loadPaths.indexOf(path) === -1
 ) %7B%0A        
@@ -1885,24 +1885,40 @@
 addFile(
+fs.realpathSync(
 resolved
 , filepa
@@ -1909,16 +1909,17 @@
 resolved
+)
 , filepa
@@ -1978,19 +1978,220 @@
 rent
- != null) %7B
+) %7B%0A    resolvedParent = _.find(this.loadPaths, function(path) %7B%0A      return parent.indexOf(path) !== -1;%0A    %7D) %7C%7C parent;%0A    resolvedParent = parent.substr(parent.indexOf(resolvedParent)).replace(/%5E%5C/*/, '');
 %0A   
@@ -2213,17 +2213,25 @@
 By.push(
-p
+resolvedP
 arent);%0A
@@ -2825,24 +2825,64 @@
  visited) %7B%0A
+  filepath = fs.realpathSync(filepath);%0A
   var visite

Normalise index paths