(function() {
  var deselectAllLayers, getAMLayerPropertyByIndex, getContexts, getDocumentProperty, getGuideInfoByindex, getLayerInfoByIndex, getOffset, getSelectionBounds, getSelectionContext, getTargetLayerRef, groupSelectedLayers, relativeRect, rulerOrigin, selectLayerAtIntex, undo, zeroes;

  undo = function() {
    return executeAction(cUndo, void 0, DialogModes.NO);
  };

  getTargetLayerRef = function() {
    var ref;
    ref = new ActionReference();
    ref.putEnumerated(cLayer, cOrdinal, cTarget);
    return ref;
  };

  groupSelectedLayers = function() {
    var desc, e;
    try {
      desc = new ActionDescriptor();
      desc.putReference(cNull, getTargetLayerRef());
      executeAction(sGroupLayersEvent, desc, DialogModes.NO);
      return true;
    } catch (_error) {
      e = _error;
      return false;
    }
  };

  deselectAllLayers = function() {
    var deselectDesc, e;
    try {
      deselectDesc = new ActionDescriptor();
      deselectDesc.putReference(cNull, getTargetLayerRef());
      return executeAction(sSelectNoLayers, deselectDesc, DialogModes.NO);
    } catch (_error) {
      e = _error;
    }
  };

  selectLayerAtIntex = function(idx, addToSelection) {
    var layerRef, layerSelectDesc;
    _.log("" + (addToSelection ? 'Add' : 'Select') + " layer at: " + idx);
    layerRef = new ActionReference();
    layerRef.putIndex(cLayer, idx);
    layerSelectDesc = new ActionDescriptor();
    layerSelectDesc.putReference(cNull, layerRef);
    layerSelectDesc.putBoolean(cMakeVisible, false);
    if (addToSelection) {
      layerSelectDesc.putEnumerated(sSelectionModifier, sSelectionModifierType, sAddToSelection);
    }
    return executeAction(cSelect, layerSelectDesc, DialogModes.NO);
  };

  zeroes = function(args) {
    var k, v;
    return ((function() {
      var _results;
      _results = [];
      for (k in args) {
        v = args[k];
        if (v !== 0) {
          _results.push(v);
        }
      }
      return _results;
    })()).length === 0;
  };

  getLayerInfoByIndex = function(idx) {
    var abBottom, abLeft, abRight, abTop, artboard, artboardRect, bottom, bounds, closing, e, guideIDs, isLayerSet, left, name, obj, right, top, type, typeID;
    name = getAMLayerPropertyByIndex(idx, cName) || 'Background';
    typeID = getAMLayerPropertyByIndex(idx, sLayerSection);
    type = typeID ? _.tSID(typeID) : 'background';
    isLayerSet = type === 'layerSectionContent' ? false : true;
    obj = {
      name: name,
      index: idx,
      isSet: isLayerSet,
      visible: getAMLayerPropertyByIndex(idx, sVisible)
    };
    try {
      artboard = getAMLayerPropertyByIndex(idx, sArtboard);
      artboardRect = _.getDescDataByKey(artboard, sArtboardRect);
      abTop = parseInt(_.getDescDataByKey(artboardRect, cTop));
      abLeft = parseInt(_.getDescDataByKey(artboardRect, cLeft));
      abBottom = parseInt(_.getDescDataByKey(artboardRect, cBottom));
      abRight = parseInt(_.getDescDataByKey(artboardRect, cRight));
      guideIDs = _.getList(_.getDescDataByKey(artboard, sGuideIDs));
      if (guideIDs.length > 0) {
        obj.guideIDs = guideIDs;
      }
      if ((abTop + abBottom + abLeft + abRight) > 0) {
        obj.artboard = {
          x1: abLeft,
          x2: abRight,
          y1: abTop,
          y2: abBottom
        };
      }
    } catch (_error) {
      e = _error;
    }
    bounds = getAMLayerPropertyByIndex(idx, sBounds);
    if (bounds) {
      top = parseInt(_.getDescDataByKey(bounds, cTop));
      left = parseInt(_.getDescDataByKey(bounds, cLeft));
      bottom = parseInt(_.getDescDataByKey(bounds, cBottom));
      right = parseInt(_.getDescDataByKey(bounds, cRight));
    }
    if (!isLayerSet) {
      obj.rect = {
        x1: left || 0,
        x2: right || 0,
        y1: top || 0,
        y2: bottom || 0
      };
    } else {
      closing = name.match(/<\/Layer group/) != null;
      if (closing) {
        obj.isClosing = true;
      }
    }
    return obj;
  };

  getGuideInfoByindex = function(idx) {
    var guide, kind, kindID, orientation, origin, ref, rulerOffset;
    ref = new ActionReference();
    ref.putIndex(cGuide, idx + 1);
    guide = executeActionGet(ref);
    origin = rulerOrigin();
    orientation = _.tSID(_.getDescDataByKey(guide, cOrientation)).charAt(0);
    rulerOffset = orientation === 'v' ? origin.x : origin.y;
    kindID = _.getDescDataByKey(guide, sKind);
    kind = kindID ? _.tSID(kindID) : 'document';
    return {
      index: idx,
      id: _.getDescDataByKey(guide, sID),
      orientation: orientation,
      location: _.getDescDataByKey(guide, sPosition) - rulerOffset,
      kind: kind,
      toString: function() {
        return "" + this.orientation + ":" + this.location;
      },
      inBounds: function(bounds) {
        var key, str, _ref;
        str = this + '\n';
        str += _.beautify(bounds);
        key = this.orientation === 'v' ? 'x' : 'y';
        return (bounds["" + key + "1"] <= (_ref = this.location) && _ref <= bounds["" + key + "2"]);
      }
    };
  };

  getAMLayerPropertyByIndex = function(idx, property) {
    var e, ref;
    ref = new ActionReference();
    ref.putProperty(cProperty, property);
    ref.putIndex(cLayer, idx);
    try {
      return _.getDescDataByKey(executeActionGet(ref), property);
    } catch (_error) {
      e = _error;
      return null;
    }
  };

  getOffset = function(key) {
    var desc, origin, ref;
    ref = new ActionReference();
    origin = _.sTID(key);
    ref.putProperty(cProperty, origin);
    ref.putEnumerated(cDocument, cOrdinal, cTarget);
    desc = executeActionGet(ref);
    if (desc.hasKey(origin)) {
      return (desc.getInteger(origin) / 65536) * -1;
    } else {
      return 0;
    }
  };

  rulerOrigin = function() {
    return {
      x: getOffset('rulerOriginH'),
      y: getOffset('rulerOriginV')
    };
  };

  relativeRect = function(relativeTo, rect) {
    return {
      x1: rect.x1 - relativeTo.x1,
      x2: rect.x2 - relativeTo.x1,
      y1: rect.y1 - relativeTo.y1,
      y2: rect.y2 - relativeTo.y1
    };
  };

  getSelectionBounds = function(bounds) {
    if (!bounds) {
      return null;
    }
    return {
      x1: parseInt(bounds[0]),
      x2: parseInt(bounds[2]),
      y1: parseInt(bounds[1]),
      y2: parseInt(bounds[3])
    };
  };

  getSelectionContext = function(doc) {
    var artboard, b, contexts, e, index, leftmost, offsetX, offsetY, overlaps, rect, topmost, _i, _len, _ref;
    try {
      b = getSelectionBounds(app.activeDocument.selection.bounds);
      overlaps = [];
      leftmost = null;
      topmost = null;
      contexts = {};
      _ref = doc.dom.artboards;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        artboard = _ref[_i];
        rect = artboard.artboard;
        if (artboard.artboardIndex > 0) {
          if ((leftmost == null) || rect.x1 < leftmost) {
            leftmost = rect.x1;
          }
          if ((topmost == null) || rect.y1 < topmost) {
            topmost = rect.y1;
          }
        }
        if ((b.x1 > rect.x2) || (b.x2 < rect.x1)) {
          continue;
        }
        if ((b.y1 > rect.y2) || (b.y2 < rect.y1)) {
          continue;
        }
        overlaps.push(artboard.artboardIndex);
      }
      index = 0;
      offsetX = b.x1 - leftmost;
      offsetY = b.y1 - topmost;
      if (overlaps.length === 2) {
        index = overlaps[1];
        artboard = doc.dom.artboards[index];
        offsetX = b.x1 - artboard.artboard.x1;
        offsetY = b.y1 - artboard.artboard.y1;
      }
      contexts[index] = {
        width: b.x2 - b.x1,
        height: b.y2 - b.y1,
        offsetX: offsetX,
        offsetY: offsetY
      };
      _.log(contexts);
      return contexts;
    } catch (_error) {
      e = _error;
      return null;
    }
  };

  getContexts = function() {
    var activeArtboards, artboard, artboards, artboardsToProcess, contexts, doc, rect, selectionContext, state, _i, _len;
    state = setup(true);
    doc = state.document;
    artboards = doc.dom.artboards;
    contexts = {};
    selectionContext = getSelectionContext(doc);
    if (selectionContext != null) {
      return selectionContext;
    }
    artboardsToProcess = artboards.length > 1 ? artboards.slice(1, artboards.length) : artboards;
    activeArtboards = doc.getActiveArtboards();
    if (activeArtboards.length > 0) {
      artboardsToProcess = activeArtboards;
    }
    for (_i = 0, _len = artboardsToProcess.length; _i < _len; _i++) {
      artboard = artboardsToProcess[_i];
      rect = artboard.rect ? artboard.rect : artboard.artboard;
      rect = relativeRect(artboard.artboard, rect);
      contexts[artboard.artboardIndex] = {
        width: rect.x2 - rect.x1,
        height: rect.y2 - rect.y1,
        offsetX: rect.x1,
        offsetY: rect.y1
      };
    }
    teardown(state);
    return contexts;
  };

  getDocumentProperty = function(property) {
    var ref;
    ref = new ActionReference();
    ref.putProperty(cProperty, property);
    ref.putEnumerated(cDocument, cOrdinal, cTarget);
    return _.getDescDataByKey(executeActionGet(ref), property);
  };

  _.ActiveDocument = (function() {
    ActiveDocument.prototype.cache = {};

    function ActiveDocument() {
      var state;
      state = setup();
      this.dom = {};
      this.getGuidesFromAM();
      this.getLayersFromAM();
      teardown(state);
    }

    ActiveDocument.prototype.countLayers = function() {
      return getDocumentProperty(cNumberOfLayers);
    };

    ActiveDocument.prototype.getTargetLayerIDs = function() {
      var background, idx, layers, n, ref, targetList;
      if (this.countLayers() === 0) {
        return [];
      }
      targetList = getDocumentProperty(sTargetLayers);
      background = hasBackground();
      if (targetList) {
        layers = (function() {
          var _i, _ref, _results;
          _results = [];
          for (n = _i = 0, _ref = targetList.count; 0 <= _ref ? _i < _ref : _i > _ref; n = 0 <= _ref ? ++_i : --_i) {
            idx = targetList.getReference(n).getIndex();
            if (background) {
              _results.push(idx);
            } else {
              _results.push(idx + 1);
            }
          }
          return _results;
        })();
        return layers.reverse();
      } else {
        ref = new ActionReference();
        ref.putProperty(cProperty, cItemIndex);
        ref.putEnumerated(cLayer, cOrdinal, cTarget);
        idx = executeActionGet(ref).getInteger(cItemIndex);
        idx = background ? idx - 1 : idx;
        if (idx !== this.countLayers()) {
          return [idx];
        }
        if (groupSelectedLayers()) {
          undo();
          return [idx];
        } else {
          return [];
        }
      }
    };

    ActiveDocument.prototype.getArtboardGuides = function(artboard) {
      var guide, guides, _i, _j, _len, _len1, _ref, _results, _results1;
      if (artboard.isDocument) {
        guides = filter(this.dom.guides, function(guide) {
          return guide.kind === 'document';
        });
        _results = [];
        for (_i = 0, _len = guides.length; _i < _len; _i++) {
          guide = guides[_i];
          _results.push(_.guideToString(guide));
        }
        return _results;
      } else {
        if (!artboard.guides) {
          return [];
        }
        _ref = artboard.guides;
        _results1 = [];
        for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
          guide = _ref[_j];
          _results1.push(_.guideToString(guide));
        }
        return _results1;
      }
    };

    ActiveDocument.prototype.getLayersFromAM = function() {
      var children, docChildren, guide, i, l, layer, parents, targetLayers, _i, _j, _len, _len1, _ref, _ref1;
      this.dom.artboards = [
        {
          name: "Document",
          isDocument: true,
          children: [],
          artboardIndex: 0,
          artboard: {
            x1: 0,
            x2: app.activeDocument.width.as('px'),
            y1: 0,
            y2: app.activeDocument.height.as('px')
          }
        }
      ];
      this.layers = {};
      targetLayers = this.getTargetLayerIDs();
      parents = {
        arr: [this.dom.artboards[0]],
        push: function(el) {
          return this.arr.push(el);
        },
        pop: function() {
          return this.arr.pop();
        },
        last: function(distance) {
          if (distance == null) {
            distance = 1;
          }
          return this.arr[this.arr.length - distance];
        }
      };
      _ref = this.getLayersInfo();
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        layer = _ref[_i];
        this.layers[layer.index] = layer;
        if (layer.isClosing) {
          parents.pop();
          continue;
        }
        layer.parent = parents.last().index;
        layer.artboardIndex = this.dom.artboards.length;
        if (layer.isSet) {
          layer.children = [];
        }
        if (layer.index === targetLayers[0]) {
          layer.target = true;
          targetLayers.shift();
        }
        if (layer.guideIDs) {
          layer.guides = filter(this.dom.guides, function(guide) {
            var id;
            return ((function() {
              var _j, _len1, _ref1, _results;
              _ref1 = layer.guideIDs;
              _results = [];
              for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
                id = _ref1[_j];
                if (id === guide.id) {
                  _results.push(true);
                }
              }
              return _results;
            })()).length;
          });
          _ref1 = layer.guides;
          for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) {
            guide = _ref1[i];
            layer.guides[i] = _.artboardRelativeGuide(guide, layer.artboard);
          }
        }
        parents.last().children.push(layer);
        if (layer.artboard) {
          this.dom.artboards.push(layer);
        }
        if (layer.isSet) {
          children = parents.last().children;
          parents.push(children[children.length - 1]);
        }
      }
      docChildren = this.dom.artboards[0].children;
      return this.dom.artboards[0].children = (function() {
        var _k, _len2, _results;
        _results = [];
        for (_k = 0, _len2 = docChildren.length; _k < _len2; _k++) {
          l = docChildren[_k];
          if (l.artboard == null) {
            _results.push(l);
          }
        }
        return _results;
      })();
    };

    ActiveDocument.prototype.getGuidesFromAM = function() {
      var guideCount, i, _i, _results;
      this.dom.guides = [];
      guideCount = app.activeDocument.guides.length;
      _results = [];
      for (i = _i = 0; 0 <= guideCount ? _i < guideCount : _i > guideCount; i = 0 <= guideCount ? ++_i : --_i) {
        _results.push(this.dom.guides.push(getGuideInfoByindex(i)));
      }
      return _results;
    };

    ActiveDocument.prototype.getLayersInfo = function() {
      var count, i, start, _i, _j, _len, _ref, _results, _results1;
      count = this.countLayers() + 1;
      start = this.getStartIndex();
      _ref = (function() {
        _results1 = [];
        for (var _j = start; start <= count ? _j < count : _j > count; start <= count ? _j++ : _j--){ _results1.push(_j); }
        return _results1;
      }).apply(this).reverse();
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        i = _ref[_i];
        _results.push(getLayerInfoByIndex(i));
      }
      return _results;
    };

    ActiveDocument.prototype.getStartIndex = function() {
      if (hasBackground()) {
        return 0;
      } else {
        return 1;
      }
    };

    ActiveDocument.prototype.getFirstTarget = function(layer) {
      var child, targets, _i, _len, _ref, _ref1;
      if (layer.target) {
        return [layer.index];
      }
      if (!((_ref = layer.children) != null ? _ref.length : void 0)) {
        return [];
      }
      targets = [];
      _ref1 = layer.children;
      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
        child = _ref1[_i];
        targets = targets.concat(arguments.callee(child));
      }
      return targets;
    };

    ActiveDocument.prototype.getLayerRect = function(layer) {
      var child, rect, _i, _len, _ref;
      if (!layer.isSet) {
        return layer.rect;
      }
      rect = null;
      _ref = layer.children;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        child = _ref[_i];
        if (!(child.rect && child.visible)) {
          continue;
        }
        if (rect == null) {
          if (!zeroes(child.rect)) {
            rect = child.rect;
          }
          continue;
        }
        rect = this.growRect(rect, child.rect);
      }
      return rect;
    };

    ActiveDocument.prototype.growRect = function(a, b) {
      if (zeroes(b)) {
        return a;
      }
      return {
        x1: b.x1 < a.x1 ? b.x1 : a.x1,
        x2: b.x2 > a.x2 ? b.x2 : a.x2,
        y1: b.y1 < a.y1 ? b.y1 : a.y1,
        y2: b.y2 > a.y2 ? b.y2 : a.y2
      };
    };

    ActiveDocument.prototype.getActiveArtboards = function(includeDocument) {
      var artboard, idx, innerTargets, rect, targetRect, targets, _i, _j, _len, _len1, _ref;
      if (includeDocument == null) {
        includeDocument = false;
      }
      targets = [];
      _ref = this.dom.artboards;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        artboard = _ref[_i];
        if (this.dom.artboards.length > 1 && artboard.artboardIndex === 0 && !includeDocument) {
          continue;
        }
        innerTargets = this.getFirstTarget(artboard);
        if (!(innerTargets.length > 0)) {
          continue;
        }
        targetRect = null;
        for (_j = 0, _len1 = innerTargets.length; _j < _len1; _j++) {
          idx = innerTargets[_j];
          if (idx === artboard.index) {
            continue;
          }
          if (!(rect = this.getLayerRect(this.layers[idx]))) {
            continue;
          }
          if (targetRect == null) {
            targetRect = rect;
            continue;
          }
          if (!zeroes(rect)) {
            targetRect = this.growRect(targetRect, rect);
          }
        }
        if (targetRect && !zeroes(targetRect)) {
          artboard.rect = targetRect;
        }
        targets.push(artboard);
      }
      return targets;
    };

    return ActiveDocument;

  })();

}).call(this);
