guideguide = {
  getInfo: function() {
    units = guideguide.before();
    var info = {
      hasOpenDocuments: app.documents.length > 0
    };
    info.ruler = friendlyUnits(units);
    if (!info.hasOpenDocuments) return JSON.stringify(info);

    var doc = app.activeDocument;
    var xOffSet = 0;
    var yOffSet = 0;

    var ref1 = new ActionReference();
    var origH = stringIDToTypeID('rulerOriginH')
    ref1.putProperty( charIDToTypeID('Prpr'), origH )
    ref1.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    var desc1 = executeActionGet(ref1);
    if(desc1.hasKey(origH)){ xOffSet = (desc1.getInteger(origH)/65536)*-1; }

    var ref2 = new ActionReference();
    var origV = stringIDToTypeID('rulerOriginV')
    ref2.putProperty( charIDToTypeID('Prpr'), origV )
    ref2.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    var desc2 = executeActionGet(ref2);
    if(desc2.hasKey(origV)){ yOffSet = (desc2.getInteger(origV)/65536)*-1;}

    try {
      doc.selection.bounds;
      info.isSelection = true;
    } catch(err) {}

    if(info.isSelection){
      info.offsetX = doc.selection.bounds[0].as('px')+xOffSet;
      info.offsetY = doc.selection.bounds[1].as('px')+yOffSet;
      info.width   = (doc.selection.bounds[2]-doc.selection.bounds[0]).as('px');
      info.height  = (doc.selection.bounds[3]-doc.selection.bounds[1]).as('px');
    } else {
      info.offsetX = xOffSet+0;
      info.offsetY = yOffSet+0;
      info.width   = doc.width.as('px');
      info.height  = doc.height.as('px');
    }

    info.resolution = doc.resolution;
    info.existingGuides = guideguide.formatGuideObjects(doc.guides);

    guideguide.after(units);
    return JSON.stringify(info);
  },
  toggleGuides: function() {
    var idslct = charIDToTypeID( "slct" );
    var desc8 = new ActionDescriptor();
    var idnull = charIDToTypeID( "null" );
    var ref2 = new ActionReference();
    var idMn = charIDToTypeID( "Mn  " );
    var idMnIt = charIDToTypeID( "MnIt" );
    var idTgld = charIDToTypeID( "Tgld" );
    ref2.putEnumerated( idMn, idMnIt, idTgld );
    desc8.putReference( idnull, ref2 );
    executeAction( idslct, desc8, DialogModes.NO );
  },
  clearGuides: function(guides) {
    var fn = "guideguide.clearGuidesAfterSuspension('" + guides + "')";
    app.activeDocument.suspendHistory("Clear Guides", fn);
  },
  clearGuidesAfterSuspension: function(guides){
    var idDlt = charIDToTypeID( "Dlt " );
    var desc5 = new ActionDescriptor();
    var idnull = charIDToTypeID( "null" );
    var ref1 = new ActionReference();
    var idGd = charIDToTypeID( "Gd  " );
    var idOrdn = charIDToTypeID( "Ordn" );
    var idAl = charIDToTypeID( "Al  " );
    ref1.putEnumerated( idGd, idOrdn, idAl );
    desc5.putReference( idnull, ref1 );
    executeAction( idDlt, desc5, DialogModes.NO );
    guideguide.addGuidesAfterSuspension(guides);
  },
  formatGuideObjects: function(guides) {
    formattedGuides = []
    for (var i=0; i<guides.length; i++) {
      formattedGuides.push({
        location: parseFloat(guides[i].coordinate.toString()),
        orientation: guides[i].direction.toString() == "Direction.VERTICAL" ? "v" : "h"
      })
    }
    return formattedGuides;
  },
  addGuides: function(guides) {
    var fn = "guideguide.addGuidesAfterSuspension('" + guides + "')";
    app.activeDocument.suspendHistory("GuideGuide!", fn);
  },
  addGuidesAfterSuspension: function(guides) {
    units = guideguide.before();
    guides = JSON.parse(guides);
    for(var i=0; i<guides.length; i++){
      g = guides[i]
      var idMk = charIDToTypeID( "Mk  " );
      var desc5 = new ActionDescriptor();
      var idNw = charIDToTypeID( "Nw  " );
      var desc6 = new ActionDescriptor();
      var idPstn = charIDToTypeID( "Pstn" );
      var idMeasure = charIDToTypeID( "#Pxl" );
      desc6.putUnitDouble( idPstn, idMeasure, g.location );
      var idOrnt = charIDToTypeID( "Ornt" );
      var idOrnt = charIDToTypeID( "Ornt" );
      var idOrientation;
      if(g.orientation=='v'){
        idOrientation = charIDToTypeID( "Vrtc" );
      } else if (g.orientation=='h') {
        idOrientation = charIDToTypeID( "Hrzn" );
      }
      desc6.putEnumerated( idOrnt, idOrnt, idOrientation );
      var idGd = charIDToTypeID( "Gd  " );
      desc5.putObject( idNw, idGd, desc6 );
      executeAction( idMk, desc5, DialogModes.NO );
    }
    guideguide.after(units);
  },
  before: function() {
    var units = app.preferences.rulerUnits
    app.preferences.rulerUnits = Units.PIXELS
    return units;
  },
  after: function(units) {
    app.preferences.rulerUnits = units;
  }
};

function friendlyUnits(units) {
  switch(units){
    case Units.CM:
      return "cm"
    case Units.INCHES:
      return "inches"
    case Units.MM:
      return "mm"
    case Units.PERCENT:
      return "percent"
    case Units.PICAS:
      return "picas";
    case Units.POINTS:
      return "points";
    default:
      return "pixels";
  }
}

"object"!=typeof JSON&&(JSON={}),function(){"use strict"
function f(t){return 10>t?"0"+t:t}function quote(t){return escapable.lastIndex=0,escapable.test(t)?'"'+t.replace(escapable,function(t){var e=meta[t]
return"string"==typeof e?e:"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}function str(t,e){var r,n,o,f,u,p=gap,i=e[t]
switch(i&&"object"==typeof i&&"function"==typeof i.toJSON&&(i=i.toJSON(t)),"function"==typeof rep&&(i=rep.call(e,t,i)),typeof i){case"string":return quote(i)
case"number":return isFinite(i)?i+"":"null"
case"boolean":case"null":return i+""
case"object":if(!i)return"null"
if(gap+=indent,u=[],"[object Array]"===Object.prototype.toString.apply(i)){for(f=i.length,r=0;f>r;r+=1)u[r]=str(r,i)||"null"
return o=0===u.length?"[]":gap?"[\n"+gap+u.join(",\n"+gap)+"\n"+p+"]":"["+u.join(",")+"]",gap=p,o}if(rep&&"object"==typeof rep)for(f=rep.length,r=0;f>r;r+=1)"string"==typeof rep[r]&&(n=rep[r],o=str(n,i),o&&u.push(quote(n)+(gap?": ":":")+o))
else for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(o=str(n,i),o&&u.push(quote(n)+(gap?": ":":")+o))
return o=0===u.length?"{}":gap?"{\n"+gap+u.join(",\n"+gap)+"\n"+p+"}":"{"+u.join(",")+"}",gap=p,o}}"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()})
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","  ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep
"function"!=typeof JSON.stringify&&(JSON.stringify=function(t,e,r){var n
if(gap="",indent="","number"==typeof r)for(n=0;r>n;n+=1)indent+=" "
else"string"==typeof r&&(indent=r)
if(rep=e,e&&"function"!=typeof e&&("object"!=typeof e||"number"!=typeof e.length))throw Error("JSON.stringify")
return str("",{"":t})}),"function"!=typeof JSON.parse&&(JSON.parse=function(text,reviver){function walk(t,e){var r,n,o=t[e]
if(o&&"object"==typeof o)for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(n=walk(o,r),void 0!==n?o[r]=n:delete o[r])
return reviver.call(t,e,o)}var j
if(text+="",cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(t){return"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})),/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j
throw new SyntaxError("JSON.parse")})}()
