var path = require('canonical-path');
var fs = require('fs');
var minimatch = require("minimatch");


// Utility wrappers over fs functions

module.exports = {
  addSymlink: addSymlink,
  removeSymlink: removeSymlink,
  removeDirSync: removeDirSync,
  lstatSyncExt: lstatSyncExt,
};

// create a new link (linkPath) that points
// to realPath - will also delete the linkPath
// if it is a preexisting folder and not itself a symbolic link before it
// starts.
function addSymlink(realPath, linkPath) {

  // check if the linkPath is a folder
  // and if so delete it
  var stat = lstatSyncExt(linkPath);

  if (stat && stat.isSymbolicLink()) {
    // todo: check if it points to realPath
    return;
  }
  if (stat && stat.isDirectory()) {
    removeDirSync(linkPath);
  }
  symLinkSyncExt(realPath, linkPath, 'dir');

}

function removeSymlink(linkPath) {
  var stat = lstatSyncExt(linkPath);
  if (!stat || !stat.isSymbolicLink()) return;

  fs.unlinkSync(linkPath);
}

// remove a dir and all of its files - sync
function removeDirSync(dirPath) {
  var files;
  try {
    files = fs.readdirSync(dirPath);
  }
  catch(e) { return; }
  if (files.length > 0) {
    for (var i = 0; i < files.length; i++) {
      var filePath = path.join(dirPath, files[i]);
      var stat = fs.lstatSync(filePath);
      if (stat.isFile() || stat.isSymbolicLink()) {
        fs.unlinkSync(filePath);
      } else {
        removeDirSync(filePath);
      }
    }
  }
  fs.rmdirSync(dirPath);
}

// same as lstatSync except returns a null for nonExistent file instead of throwing
function lstatSyncExt(filePath) {
  try {
    var stat = fs.lstatSync(filePath);
  } catch (e) {
    if(e.code == 'ENOENT') return null;
    throw e;
  }
  return stat;
}

function symLinkSyncExt(realPath, linkPath, type) {
  // fs.symlink requires the real path to be fully resolved.
  realPath = path.resolve(realPath);
  try {
    fs.symlinkSync(realPath, linkPath, type);
  } catch (e) {
    var msg = "Unable to create symlink: " + linkPath;
    if (e.code == "EPERM") {
      msg += "\nPermissions issue, on windows this function must be run as an administrator."
    }
    console.log(msg + "\n" + e);
  }
}

// Talk to Jay - not currently needed.
//
//function globWithIgnore(basePath, globs, ignoreGlobs, options) {
//  options = options || {};
//  options.filters = globs.map(function (glob) {
//    return minimatch.filter(glob);
//  });
//  options.ignoreFilters = ignoreGlobs && ignoreGlobs.map(function(glob) {
//      return minimatch.filter(glob);
//    });
//  options.ignoreSymlink = options.ignoreSymlink == null ? true : false;
//  return globSyncCore(basePath, options);
//}
//
//function globSyncCore(basePath, options) {
//  var results = [];
//  var files;
//  try {
//    files = fs.readdirSync(basePath);
//  }
//  catch(e) { return results; }
//
//  files.forEach(function(file) {
//    var filePath = path.join(basePath, file);
//    var shouldIgnore = options.ignoreFilters && options.ignoreFilters.some(function(filter) {
//        return filter(filePath);
//      });
//    if (shouldIgnore) return;
//
//    var stat = fs.lstatSync(filePath);
//
//    if (stat.isDirectory()) {
//      if (stat.isSymbolicLink() && options.ignoreSymlink) {
//        // do nothing
//      } else {
//        var partialResults = globSyncCore(filePath, options);
//        Array.prototype.push.apply(results, partialResults);
//      }
//    } else {
//      var ok = options.filters.every(function(filter) {
//        return filter(filePath);
//      });
//      if (ok) {
//        results.push(filePath);
//      }
//    }
//  });
//  return results;
//}