(function() {
  var GuideGuide, addGuide, addGuides, clearAllGuides, clearArtboardGuides, clearCanvasGuides, clearGuideByIndex, clearGuides, clearGuidesInBounds, clearOrientationGuides, duplicateGuidesToArtboards, duplicateGuidesToOpenDocuments, getGuidesFromTargetContexts, getSnap, getUses, hostStorage, incrimentUses, setup, suspend, teardown, trialExpired;

  getSnap = function() {
    return true;
  };

  getUses = function() {
    var count, e;
    count = 0;
    try {
      count = hostStorage().getInteger(sFreeUses);
    } catch (_error) {
      e = _error;
    }
    return count;
  };

  incrimentUses = function() {
    var desc;
    desc = new ActionDescriptor();
    desc.putInteger(sFreeUses, getUses() + 1);
    return app.putCustomOptions(REGISTRY_KEY, desc, true);
  };

  hostStorage = function() {
    var desc, e, storage;
    storage = {};
    try {
      storage = app.getCustomOptions(REGISTRY_KEY);
    } catch (_error) {
      e = _error;
      desc = new ActionDescriptor();
      desc.putBoolean(sInit, true);
      app.putCustomOptions(REGISTRY_KEY, desc, true);
      storage = app.getCustomOptions(REGISTRY_KEY);
    }
    return storage;
  };

  trialExpired = function() {
    return getUses() > 30;
  };

  suspend = function(label, method, data) {
    var fn;
    _.log("");
    if (data && typeof data === 'object') {
      data = "'" + (JSON.stringify(data)) + "'";
    }
    fn = "" + method + "(" + (data ? '\'' + data + '\'' : '') + ")";
    _.log("Suspending: " + fn);
    return app.activeDocument.suspendHistory(label, fn);
  };

  addGuide = function(str, artboardGuide) {
    var guide, guideDesc, newGuideDesc, orientation, origin, rulerOffset, target;
    _.log("Adding " + (artboardGuide ? 'artboard ' : '') + "guide: " + str);
    guide = _.guideToObject(str);
    orientation = guide.orientation === 'v' ? cVertical : cHorizontal;
    origin = rulerOrigin();
    rulerOffset = guide.orientation === 'v' ? origin.x : origin.y;
    guideDesc = new ActionDescriptor();
    guideDesc.putUnitDouble(cPosition, cPixel, guide.location + rulerOffset);
    guideDesc.putEnumerated(cOrientation, cOrientation, orientation);
    guideDesc.putEnumerated(cKind, cKind, cDocument);
    newGuideDesc = new ActionDescriptor();
    newGuideDesc.putObject(cNew, cGuide, guideDesc);
    target = artboardGuide ? sSelectedArtboard : sGuideTargetCanvas;
    newGuideDesc.putEnumerated(sGuideTarget, sGuideTarget, target);
    return executeAction(cMake, newGuideDesc, DialogModes.NO);
  };

  setup = function(document) {
    var k, obj, units, v;
    units = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;
    obj = {
      units: units
    };
    if (!document) {
      return obj;
    }
    document = new _.ActiveDocument();
    obj.targetLayers = (function() {
      var _ref, _results;
      _ref = document.layers;
      _results = [];
      for (k in _ref) {
        v = _ref[k];
        if (v.target === true) {
          _results.push(v.index);
        }
      }
      return _results;
    })();
    obj.document = document;
    return obj;
  };

  teardown = function(state) {
    var i, index, _i, _len, _ref, _results;
    _.log("Restoring to previous state: ");
    _.log("  Units: " + (state.units.toString()));
    if (state.targetLayers) {
      _.log("  Layers: " + state.targetLayers);
    }
    app.preferences.rulerUnits = state.units;
    if (!state.targetLayers) {
      return;
    }
    if (state.targetLayers.length === 0) {
      return deselectAllLayers();
    }
    _ref = state.targetLayers;
    _results = [];
    for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
      index = _ref[i];
      _results.push(selectLayerAtIntex(index, i !== 0));
    }
    return _results;
  };

  addGuides = function(contexts) {
    var artboard, artboardGuides, doc, guides, key, state, token, _i, _len;
    _.log("Adding guides");
    _.log("Data from GuideGuide:", contexts);
    contexts = JSON.parse(contexts);
    state = setup(true);
    doc = state.document;
    for (key in contexts) {
      guides = contexts[key];
      artboard = doc.dom.artboards[parseInt(key)];
      _.log("Current Artboard: " + artboard.name);
      artboardGuides = doc.getArtboardGuides(artboard);
      if (!artboard.isDocument) {
        selectLayerAtIntex(artboard.index);
      }
      for (_i = 0, _len = guides.length; _i < _len; _i++) {
        token = guides[_i];
        if (filter(artboardGuides, function(g) {
          return g === token;
        }).length > 0) {
          _.log("Skipping already existing guide: " + token);
          continue;
        }
        addGuide(token, parseInt(key) > 0);
      }
    }
    return teardown(state);
  };

  clearCanvasGuides = function() {
    var e;
    try {
      return executeAction(sClearCanvasGuides, void 0, DialogModes.NO);
    } catch (_error) {
      e = _error;
      return clearAllGuides();
    }
  };

  clearArtboardGuides = function() {
    var e;
    try {
      return executeAction(sClearArtboardGuides, void 0, DialogModes.NO);
    } catch (_error) {
      e = _error;
      return clearAllGuides();
    }
  };

  clearAllGuides = function() {
    var desc, e, ref;
    try {
      return executeAction(sClearAllGuides, void 0, DialogModes.NO);
    } catch (_error) {
      e = _error;
      desc = new ActionDescriptor();
      ref = new ActionReference();
      ref.putEnumerated(cGuide, cOrdinal, cAll);
      desc.putReference(cNull, ref);
      return executeAction(cDelete, desc, DialogModes.NO);
    }
  };

  clearGuideByIndex = function(idx) {
    var guideDesc, guideRef;
    guideRef = new ActionReference();
    guideRef.putIndex(cGuide, idx + 1);
    guideDesc = new ActionDescriptor();
    guideDesc.putReference(cNull, guideRef);
    return executeAction(cDelete, guideDesc, DialogModes.NO);
  };

  clearGuidesInBounds = function(guides, bounds) {
    var guide, _i, _results;
    if (!((guides != null) && (bounds != null))) {
      return;
    }
    _results = [];
    for (_i = guides.length - 1; _i >= 0; _i += -1) {
      guide = guides[_i];
      if (_.guideInBounds(guide, bounds)) {
        _.log("Deleting: " + (_.guideToString(guide)) + " at index " + guide.index);
        _results.push(clearGuideByIndex(guide.index));
      } else {
        _results.push(void 0);
      }
    }
    return _results;
  };

  clearGuides = function(orientation) {
    var activeArtboards, artboard, bounds, doc, e, guides, state, _i, _len;
    _.log("Clearing guides");
    state = setup(true);
    doc = state.document;
    _.log(state.units.toString());
    try {
      bounds = getSelectionBounds(app.activeDocument.selection.bounds);
      _.log('Clearing guides in selection: ', bounds);
      clearGuidesInBounds(doc.dom.guides, bounds);
      teardown(state);
      return;
    } catch (_error) {
      e = _error;
    }
    activeArtboards = doc.getActiveArtboards();
    if (activeArtboards.length === 0) {
      if (doc.dom.artboards.length > 1) {
        activeArtboards = doc.dom.artboards.slice(1, doc.dom.artboards.length);
      } else {
        activeArtboards = [doc.dom.artboards[0]];
      }
    }
    for (_i = 0, _len = activeArtboards.length; _i < _len; _i++) {
      artboard = activeArtboards[_i];
      if (artboard.rect != null) {
        _.log("Clearing specific guides");
        guides = artboard.guides;
        if (artboard.isDocument) {
          guides = filter(doc.dom.guides, function(g) {
            return g.kind === 'document';
          });
        }
        clearGuidesInBounds(guides, relativeRect(artboard.artboard, artboard.rect));
        continue;
      }
      if (artboard.isDocument) {
        clearCanvasGuides();
        continue;
      }
      if (!artboard.isDocument) {
        selectLayerAtIntex(artboard.index);
      }
      _.log("Clearing artboard guides in: " + artboard.name);
      clearArtboardGuides();
    }
    return teardown(state);
  };

  getGuidesFromTargetContexts = function(compact) {
    var activeArtboards, artboard, artboardIndex, context, contexts, doc, e, g, guide, guides, key, rect, relativeGuide, selection, selectionGuides, sourceArtboards, token, tokens, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref;
    if (compact == null) {
      compact = false;
    }
    doc = new _.ActiveDocument();
    sourceArtboards = doc.dom.artboards;
    activeArtboards = doc.getActiveArtboards();
    if (activeArtboards.length > 0) {
      sourceArtboards = activeArtboards;
    }
    contexts = {};
    try {
      selection = getSelectionBounds(app.activeDocument.selection.bounds);
      selectionGuides = [];
      sourceArtboards = doc.dom.artboards;
    } catch (_error) {
      e = _error;
    }
    for (_i = 0, _len = sourceArtboards.length; _i < _len; _i++) {
      artboard = sourceArtboards[_i];
      guides = artboard.guides;
      if (artboard.isDocument) {
        guides = filter(doc.dom.guides, function(g) {
          return g.kind === 'document';
        });
      }
      if (!guides) {
        continue;
      }
      if (selection != null) {
        guides = (function() {
          var _j, _len1, _results;
          _results = [];
          for (_j = 0, _len1 = guides.length; _j < _len1; _j++) {
            guide = guides[_j];
            if (_.guideInBounds(guide, selection, !artboard.isDocument)) {
              _results.push(guide);
            }
          }
          return _results;
        })();
      }
      if (artboard.rect != null) {
        if (artboard.rect != null) {
          rect = relativeRect(artboard.artboard, artboard.rect);
        }
        guides = (function() {
          var _j, _len1, _results;
          _results = [];
          for (_j = 0, _len1 = guides.length; _j < _len1; _j++) {
            g = guides[_j];
            if (_.guideInBounds(g, rect)) {
              _results.push(g);
            }
          }
          return _results;
        })();
      } else {

      }
      _ref = doc.dom.artboards;
      for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
        artboard = _ref[_j];
        if ((selection == null) && artboard.isDocument && doc.dom.artboards.length > 1) {
          continue;
        }
        artboardIndex = artboard.artboardIndex;
        contexts[artboardIndex] || (contexts[artboardIndex] = []);
        tokens = [];
        for (_k = 0, _len2 = guides.length; _k < _len2; _k++) {
          guide = guides[_k];
          if (guide.kind === 'document') {
            if (_.guideInBounds(guide, artboard.artboard)) {
              relativeGuide = _.artboardRelativeGuide(guide, artboard.artboard);
              tokens.push(_.guideToString(relativeGuide));
            }
            continue;
          }
          tokens.push(_.guideToString(guide));
        }
        contexts[artboardIndex] = contexts[artboardIndex].concat(tokens);
      }
    }
    if (compact) {
      tokens = {};
      for (key in contexts) {
        context = contexts[key];
        for (_l = 0, _len3 = context.length; _l < _len3; _l++) {
          token = context[_l];
          tokens[token] = token;
        }
      }
      return {
        0: (function() {
          var _results;
          _results = [];
          for (key in tokens) {
            token = tokens[key];
            _results.push(token);
          }
          return _results;
        })()
      };
    }
    return contexts;
  };

  duplicateGuidesToArtboards = function() {
    var contexts;
    _.log('Duplicating guides to all artboards');
    contexts = getGuidesFromTargetContexts();
    delete contexts[0];
    _.log('Duplicating from contexts:', contexts);
    return addGuides(JSON.stringify(contexts));
  };

  duplicateGuidesToOpenDocuments = function() {
    var activeDocument, contexts, doc, _i, _len, _ref;
    _.log('Duplicating guides to all open documents');
    activeDocument = app.activeDocument;
    _.log("Active document is: " + activeDocument.id);
    contexts = getGuidesFromTargetContexts(true);
    _.log("Duplicating from contexts:", contexts);
    if (contexts[0].length === 0) {
      return;
    }
    _ref = app.documents;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      doc = _ref[_i];
      app.activeDocument = doc;
      if (app.activeDocument.id === activeDocument.id) {
        continue;
      }
      _.log("Duplicating guides to: " + doc.id);
      suspend($.GuideGuideMessages['historyDuplicateGuidesFrom'] + ' ' + activeDocument.name, 'addGuides', JSON.stringify(contexts));
    }
    return app.activeDocument = activeDocument;
  };

  clearOrientationGuides = function(orientation) {
    var activeArtboards, artboard, artboardsToProcess, doc, guide, guides, guidesToClear, orientationString, state, _i, _j, _len, _len1;
    orientationString = orientation === 'v' ? 'vertical' : 'horizontal';
    _.log("Clearing " + orientationString + " guides");
    state = setup(true);
    doc = state.document;
    artboardsToProcess = doc.dom.artboards;
    activeArtboards = doc.getActiveArtboards(true);
    if (activeArtboards.length > 0) {
      artboardsToProcess = activeArtboards;
    }
    guidesToClear = [];
    for (_i = 0, _len = artboardsToProcess.length; _i < _len; _i++) {
      artboard = artboardsToProcess[_i];
      guides = artboard.guides;
      if (artboard.isDocument) {
        guides = filter(doc.dom.guides, function(g) {
          return g.kind === 'document';
        });
      }
      if (!guides) {
        continue;
      }
      guides = filter(guides, function(guide) {
        var inBounds, oriented, rect;
        oriented = guide.orientation === orientation;
        inBounds = true;
        if (artboard.rect != null) {
          rect = relativeRect(artboard.artboard, artboard.rect);
          inBounds = _.guideInBounds(guide, rect);
        }
        return oriented && inBounds;
      });
      guidesToClear = guidesToClear.concat(guides);
    }
    guidesToClear.sort(function(a, b) {
      return parseInt(a.index) < parseInt(b.index);
    });
    for (_j = 0, _len1 = guidesToClear.length; _j < _len1; _j++) {
      guide = guidesToClear[_j];
      clearGuideByIndex(guide.index);
    }
    return teardown(state);
  };

  GuideGuide = (function() {
    GuideGuide.prototype.capabilities = {
      artboardGuides: false
    };

    function GuideGuide() {}

    GuideGuide.prototype.getAppInfo = function() {
      return JSON.stringify({
        snap: getSnap(),
        capabilities: this.capabilities,
        trialExpired: trialExpired()
      });
    };

    GuideGuide.prototype.getExistingGuides = function() {
      var contexts;
      if (!this.hasOpenDocument()) {
        return '[]';
      }
      contexts = getGuidesFromTargetContexts(true);
      return JSON.stringify(contexts['0']);
    };

    GuideGuide.prototype.hasOpenDocument = function() {
      if (!(app.documents.length > 0)) {
        return false;
      }
      return JSON.stringify({
        resolution: app.activeDocument.resolution
      });
    };

    GuideGuide.prototype.getDocumentRulerUnits = function() {
      if (!this.hasOpenDocument()) {
        return '';
      }
      return _.friendlyUnits(app.preferences.rulerUnits);
    };

    GuideGuide.prototype.addGuides = function(guides) {
      if (!this.hasOpenDocument()) {
        return null;
      }
      incrimentUses();
      suspend($.GuideGuideMessages['btnAddGuides'], 'addGuides', guides);
      return null;
    };

    GuideGuide.prototype.getContexts = function() {
      var contexts;
      if (!this.hasOpenDocument()) {
        return '{}';
      }
      contexts = getContexts();
      _.log("");
      _.log("Contexts requested, got:", contexts);
      return JSON.stringify(contexts);
    };

    GuideGuide.prototype.clearGuides = function() {
      if (!this.hasOpenDocument()) {
        return null;
      }
      suspend($.GuideGuideMessages['tooltipClearGuides'], 'clearGuides');
      return null;
    };

    GuideGuide.prototype.openInstallDirectory = function(path) {
      var e;
      try {
        _.log("Opening folder: " + path);
        return File(path).execute();
      } catch (_error) {
        e = _error;
        return _.log(e);
      }
    };

    GuideGuide.prototype.toggleLogging = function(openFile) {
      var LOGGING_ENABLED, e, file;
      if (openFile == null) {
        openFile = true;
      }
      if (openFile === 'true') {
        openFile = true;
      }
      try {
        LOGGING_ENABLED = !LOGGING_ENABLED;
        if (LOGGING_ENABLED) {
          _.log("    Logging enabled");
          file = _.dumpLogFileTo(getLogPath());
          if (openFile === true) {
            return file.execute();
          }
        } else {
          return _.log("Logging disabled");
        }
      } catch (_error) {
        e = _error;
        return alert(e);
      }
    };

    GuideGuide.prototype.duplicateGuidesToArtboards = function() {
      if (!this.hasOpenDocument()) {
        return null;
      }
      suspend($.GuideGuideMessages['menuDuplicateToArtboards'], 'duplicateGuidesToArtboards');
      return null;
    };

    GuideGuide.prototype.duplicateGuidesToOpenDocuments = function() {
      if (!this.hasOpenDocument()) {
        return null;
      }
      suspend($.GuideGuideMessages['menuDuplicateToOpenDocuments'], 'duplicateGuidesToOpenDocuments');
      return null;
    };

    GuideGuide.prototype.clearCanvasGuides = function() {
      if (!this.hasOpenDocument()) {
        return null;
      }
      return clearCanvasGuides();
    };

    GuideGuide.prototype.clearArtboardGuides = function() {
      if (!this.hasOpenDocument()) {
        return null;
      }
      return clearArtboardGuides();
    };

    GuideGuide.prototype.clearAllGuides = function() {
      if (!this.hasOpenDocument()) {
        return null;
      }
      return clearAllGuides();
    };

    GuideGuide.prototype.clearOrientationGuides = function(orientation) {
      var labelKey;
      if (!this.hasOpenDocument()) {
        return null;
      }
      labelKey = orientation === 'v' ? 'menuClearVerticalGuides' : 'menuClearHorizontalGuides';
      return suspend($.GuideGuideMessages[labelKey], 'clearOrientationGuides', orientation);
    };

    GuideGuide.prototype.toggleGuides = function() {
      var desc, ref;
      desc = new ActionDescriptor();
      ref = new ActionReference();
      ref.putEnumerated(cMenu, cMenuItem, cToggleGuides);
      desc.putReference(cNull, ref);
      return executeAction(cSelect, desc, DialogModes.NO);
    };

    GuideGuide.prototype.getDataDir = function() {
      return File(DATA_DIRECTORY).fsName;
    };

    GuideGuide.prototype.changeDataDir = function(to) {
      var from, result;
      to = File(decodeURI(to)).absoluteURI;
      from = DATA_DIRECTORY;
      _.log("Changing DATA_DIRECTORY from " + from + " to " + to);
      if (to === from) {
        return;
      }
      result = setDataFolder(to);
      if (result instanceof Folder) {
        if (!File(dataPathFor(to)).exists) {
          cpFile(dataPathFor(from), dataPathFor(to));
        }
        _.dumpLogFileTo(getLogPath());
        return File(DATA_DIRECTORY).fsName;
      } else {
        _.log(_.formatError(result));
        return null;
      }
    };

    return GuideGuide;

  })();

  $.GuideGuide = new GuideGuide();

}).call(this);
