(function() {
  var DATA_DIRECTORY, LOGGING_ENABLED, REGISTRY_KEY, Utilities, cpFile, createFileAt, filter, hasBackground, setDataFolder, writeLineToFile, _;

  REGISTRY_KEY = 'GuideGuide';

  LOGGING_ENABLED = false;

  DATA_DIRECTORY = null;

  cpFile = function(src, dest) {
    var e;
    try {
      if (typeof src === 'string') {
        src = File(src);
      }
      if (typeof dest === 'string') {
        dest = File(dest);
      }
      if (src.copy(dest)) {
        return _.log("cp " + src.absoluteURI + " -> " + dest.absoluteURI);
      }
      return _.log("Fail: cp " + src.absoluteURI + " -> " + dest.absoluteURI + " (" + src.error + ")");
    } catch (_error) {
      e = _error;
      return alert(e);
    }
  };

  setDataFolder = function(path) {
    var dataFolder, desc, e;
    try {
      if (path instanceof Folder) {
        path = path.absoluteURI;
      }
      dataFolder = Folder(path);
      if (!dataFolder.exists) {
        dataFolder.create();
      }
      if (!dataFolder.exists) {
        throw Error('Does not exist');
      }
      DATA_DIRECTORY = dataFolder.absoluteURI;
      desc = new ActionDescriptor();
      desc.putString(sDataDir, dataFolder.absoluteURI);
      app.putCustomOptions(REGISTRY_KEY, desc, true);
      return dataFolder;
    } catch (_error) {
      e = _error;
      return Error("Cannot set data folder to " + (encodeURI(dataFolder.absoluteURI)) + " because:\n" + (_.formatError(e)));
    }
  };

  createFileAt = function(path, initData) {
    var file, folder;
    if (path == null) {
      return;
    }
    file = new File(decodeURI(path));
    folder = Folder(file.path);
    if (!folder.exists) {
      folder.create();
    }
    if (file.open('w')) {
      if (_.isMac()) {
        file.lineFeed = 'unix';
      }
      file.encoding = 'UTF8';
      if (initData) {
        writeLineToFile(initData, file);
      }
      return file;
    } else {
      throw Error("Unable to create file at " + path + "\n" + file.error);
    }
  };

  filter = function(array, callback) {
    var item, _i, _len, _results;
    _results = [];
    for (_i = 0, _len = array.length; _i < _len; _i++) {
      item = array[_i];
      if (callback(item)) {
        _results.push(item);
      }
    }
    return _results;
  };

  hasBackground = function() {
    var e;
    try {
      app.activeDocument.backgroundLayer;
      return true;
    } catch (_error) {
      e = _error;
      return false;
    }
  };

  writeLineToFile = function(str, file) {
    if (!file.open('e')) {
      throw Error("Unable to open file: " + file);
    }
    file.seek(0, 2);
    if (!file.writeln(str)) {
      throw Error("Unable to write file: " + file);
    }
  };

  Utilities = (function() {
    Utilities.prototype.logCache = '';

    function Utilities() {
      return;
    }

    Utilities.prototype.isMac = function() {
      return !$.os.match(/windows/i);
    };

    Utilities.prototype.cTID = function(s) {
      return app.charIDToTypeID(s);
    };

    Utilities.prototype.sTID = function(s) {
      return app.stringIDToTypeID(s);
    };

    Utilities.prototype.tSID = function(n) {
      return app.typeIDToStringID(n);
    };

    Utilities.prototype.log = function() {
      var arg, file, _i, _len, _results;
      _results = [];
      for (_i = 0, _len = arguments.length; _i < _len; _i++) {
        arg = arguments[_i];
        if (typeof arg !== 'string') {
          arg = this.beautify(arg);
        }
        arg = decodeURI(arg);
        this.logCache += arg + '\n';
        if (!LOGGING_ENABLED) {
          continue;
        }
        file = File(getLogPath());
        if (file.exists) {
          _results.push(writeLineToFile(arg, file));
        } else {
          _results.push(void 0);
        }
      }
      return _results;
    };

    Utilities.prototype.dumpLogFileTo = function(path) {
      return createFileAt(path, this.logCache.replace(/\n$/, ''));
    };

    Utilities.prototype.formatError = function(e, source) {
      var context, first, i, last;
      if (source == null) {
        source = '';
      }
      try {
        context = e.source.split('\n');
        first = e.line - 10 > 0 ? e.line - 10 : 0;
        last = e.line + 10 < context.length - 1 ? e.line + 10 : context.length - 1;
        return "////////////////////////////////////////\n\n  Error: " + e.message + "\n  File: " + e.fileName + "\n  Line: " + e.line + "\n  Context:\n\n  " + (((function() {
          var _i, _results;
          _results = [];
          for (i = _i = first; first <= last ? _i < last : _i > last; i = first <= last ? ++_i : --_i) {
            _results.push((i + 1) + '    ' + context[i]);
          }
          return _results;
        })()).join('\n  ')) + "\n\n  When evalutating: " + source + "\n\n////////////////////////////////////////\n";
      } catch (_error) {
        e = _error;
        return alert(e);
      }
    };

    Utilities.prototype.listKeys = function(desc) {
      var n, str, _i, _ref;
      str = "Total keys: " + desc.count + "\n";
      for (n = _i = 0, _ref = desc.count; 0 <= _ref ? _i < _ref : _i > _ref; n = 0 <= _ref ? ++_i : --_i) {
        str += "" + n + ": " + (this.tSID(desc.getKey(n))) + "\n";
      }
      return alert(str);
    };

    Utilities.prototype.getDescDataByKey = function(desc, typeID) {
      if ((desc.hasKey != null) && !desc.hasKey(typeID)) {
        return null;
      }
      switch (desc.getType(typeID)) {
        case DescValueType.REFERENCETYPE:
          return executeActionGet(desc.getReference(typeID));
        case DescValueType.LISTTYPE:
          return desc.getList(typeID);
        case DescValueType.INTEGERTYPE:
          return desc.getInteger(typeID);
        case DescValueType.OBJECTTYPE:
          return desc.getObjectValue(typeID);
        case DescValueType.STRINGTYPE:
          return desc.getString(typeID);
        case DescValueType.BOOLEANTYPE:
          return desc.getBoolean(typeID);
        case DescValueType.ENUMERATEDTYPE:
          return desc.getEnumerationValue(typeID);
        case DescValueType.DOUBLETYPE:
          return desc.getDouble(typeID);
        case DescValueType.UNITDOUBLE:
          return desc.getUnitDoubleValue(typeID);
        default:
          return alert("Cannot get data from " + (desc.getType(typeID)));
      }
    };

    Utilities.prototype.getList = function(list) {
      var n, _i, _ref, _results;
      _results = [];
      for (n = _i = 0, _ref = list.count; 0 <= _ref ? _i < _ref : _i > _ref; n = 0 <= _ref ? ++_i : --_i) {
        _results.push(this.getDescDataByKey(list, n));
      }
      return _results;
    };

    Utilities.prototype.beautify = function(obj) {
      return JSON.stringify(obj, null, 2);
    };

    Utilities.prototype.guideToString = function(obj) {
      return "" + obj.orientation + ":" + obj.location;
    };

    Utilities.prototype.guideToObject = function(string) {
      var arr;
      arr = /([hv]):(-?\d+)/.exec(string).slice(1, 3);
      return {
        orientation: arr[0],
        location: parseFloat(arr[1])
      };
    };

    Utilities.prototype.guideInBounds = function(guide, bounds, canvasLocation) {
      var key, location;
      if (canvasLocation == null) {
        canvasLocation = false;
      }
      location = canvasLocation ? guide.canvasLocation : guide.location;
      key = guide.orientation === 'v' ? 'x' : 'y';
      return (bounds["" + key + "1"] <= location && location <= bounds["" + key + "2"]);
    };

    Utilities.prototype.artboardRelativeGuide = function(guide, rect) {
      var clone, k, offset, v;
      clone = new Object();
      for (k in guide) {
        v = guide[k];
        clone[k] = v;
      }
      offset = clone.orientation === 'v' ? rect.x1 : rect.y1;
      clone.canvasLocation = clone.location;
      clone.location = clone.canvasLocation - offset;
      return clone;
    };

    Utilities.prototype.friendlyUnits = function(units) {
      switch (units) {
        case Units.CM:
          return "cm";
        case Units.INCHES:
          return "in";
        case Units.MM:
          return "mm";
        case Units.PERCENT:
          return "%";
        case Units.PICAS:
          return "picas";
        case Units.POINTS:
          return "points";
        default:
          return "px";
      }
    };

    return Utilities;

  })();

  _ = new Utilities();

  $._ = _;

}).call(this);
