// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var CodeSign, DropboxPreset, GitPreset, GlobberPreset, KbPreset, PackageJson, SummarizedItem, constants, iced, item_types, json_stringify_sorted, make_esc, path, utils, vc, __iced_k, __iced_k_noop,
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  iced = require('iced-runtime').iced;
  __iced_k = __iced_k_noop = function() {};

  path = require('path');

  make_esc = require('iced-error').make_esc;

  PackageJson = require('./package').PackageJson;

  constants = require('./constants');

  item_types = require('./constants').item_types;

  SummarizedItem = require('./summarized_item').SummarizedItem;

  GitPreset = require('./preset/git');

  KbPreset = require('./preset/kb');

  DropboxPreset = require('./preset/dropbox');

  GlobberPreset = require('./preset/globber');

  json_stringify_sorted = require('iced-utils').util.json_stringify_sorted;

  vc = constants.verify_codes;

  utils = require('./utils');

  CodeSign = (function() {
    function CodeSign(root_dir, opts) {
      var _base, _base1;
      this.root_dir = path.resolve(root_dir);
      this.root_item = null;
      this.presets = [];
      this.opts = opts || {};
      (_base = this.opts).ignore || (_base.ignore = []);
      (_base1 = this.opts).presets || (_base1.presets = []);
      this.signatures = [];
      this._init_done = false;
      this._create_presets();
    }

    CodeSign.prototype.walk = function(cb) {
      var esc, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      esc = make_esc(cb, "SummarizedItem::load");
      this.root_item = new SummarizedItem({
        fname: '.',
        parent_path: '',
        codesign: this
      });
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/codesign/src/codesign.iced",
            funcname: "CodeSign.walk"
          });
          _this.root_item.load_traverse(esc(__iced_deferrals.defer({
            lineno: 52
          })));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          _this._init_done = true;
          return cb(null);
        };
      })(this));
    };

    CodeSign.is_valid_preset = function(p) {
      return constants.presets[p.toLowerCase()] != null;
    };

    CodeSign.prototype.attach_sig = function(signer, signature) {
      return this.signatures.push({
        signer: signer,
        signature: signature
      });
    };

    CodeSign.prototype.to_json_obj = function() {

      /*
      a deterministic representation of the summary
       */
      return {
        meta: {
          version: new PackageJson().version()
        },
        ignore: this.opts.ignore,
        presets: this.opts.presets,
        found: this.root_item.walk_to_array(),
        signatures: this.signatures
      };
    };

    CodeSign.prototype.signable_payload = function() {
      return CodeSign.json_obj_to_signable_payload(this.to_json_obj());
    };

    CodeSign.json_obj_to_signable_payload = function(o) {
      var f, k, so, v, _i, _j, _len, _len1, _ref, _ref1;
      so = {};
      _ref = ['meta', 'ignore', 'presets', 'found'];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        k = _ref[_i];
        so[k] = o[k];
      }
      _ref1 = so.found;
      for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
        f = _ref1[_j];
        for (k in f) {
          v = f[k];
          if (k[0] === '_') {
            delete f[k];
          }
        }
      }
      return json_stringify_sorted(so);
    };

    CodeSign.prototype._should_ignore = function(path_to_file, cb) {
      var p, r, res, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      res = false;
      (function(_this) {
        return (function(__iced_k) {
          if (__indexOf.call(_this.opts.ignore, path_to_file) >= 0) {
            return __iced_k(res = true);
          } else {
            (function(__iced_k) {
              var _i, _len, _ref, _results, _while;
              _ref = _this.presets;
              _len = _ref.length;
              _i = 0;
              _results = [];
              _while = function(__iced_k) {
                var _break, _continue, _next;
                _break = function() {
                  return __iced_k(_results);
                };
                _continue = function() {
                  return iced.trampoline(function() {
                    ++_i;
                    return _while(__iced_k);
                  });
                };
                _next = function(__iced_next_arg) {
                  _results.push(__iced_next_arg);
                  return _continue();
                };
                if (!(_i < _len)) {
                  return _break();
                } else {
                  p = _ref[_i];
                  (function(__iced_k) {
                    __iced_deferrals = new iced.Deferrals(__iced_k, {
                      parent: ___iced_passed_deferral,
                      filename: "/Users/max/src/keybase/codesign/src/codesign.iced",
                      funcname: "CodeSign._should_ignore"
                    });
                    p.handle(_this.root_dir, path_to_file, __iced_deferrals.defer({
                      assign_fn: (function() {
                        return function() {
                          return r = arguments[0];
                        };
                      })(),
                      lineno: 103
                    }));
                    __iced_deferrals._fulfill();
                  })(function() {
                    (function(__iced_k) {
                      if (r === constants.ignore_res.IGNORE) {
                        res = true;
                        (function(__iced_k) {
_break()
                        })(__iced_k);
                      } else {
                        (function(__iced_k) {
                          if (r === constants.ignore_res.DONT_IGNORE) {
                            res = false;
                            (function(__iced_k) {
_break()
                            })(__iced_k);
                          } else {
                            return __iced_k();
                          }
                        })(__iced_k);
                      }
                    })(_next);
                  });
                }
              };
              _while(__iced_k);
            })(__iced_k);
          }
        });
      })(this)((function(_this) {
        return function() {
          return cb(null, res);
        };
      })(this));
    };

    CodeSign.prototype._hash_match = function(h1, h2) {
      return (!((h1 != null) || (h2 != null))) || ((h1 != null ? h1.hash : void 0) === (h2 != null ? h2.hash : void 0));
    };

    CodeSign.prototype._hash_alt_match = function(h1, h2) {
      return (!((h1 != null) || (h2 != null))) || ((h1 != null ? h1.hash : void 0) === (h2 != null ? h2.hash : void 0)) || ((h1 != null ? h1.alt_hash : void 0) === (h2 != null ? h2.hash : void 0)) || ((h1 != null ? h1.hash : void 0) === (h2 != null ? h2.alt_hash : void 0));
    };

    CodeSign.prototype.compare_to_json_obj = function(obj, cb) {

      /*
      calls back with an array of problems
      each item in the array is a pair [code, {got, expected}]
       */
      var exp_by_path, expected, f, got, got_by_path, msg, p1, probs, status, _i, _j, _len, _len1, _ref, _ref1;
      probs = [];
      got_by_path = {};
      exp_by_path = {};
      _ref = this.to_json_obj().found;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        f = _ref[_i];
        got_by_path[f.path] = f;
      }
      _ref1 = obj.found;
      for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
        f = _ref1[_j];
        exp_by_path[f.path] = f;
      }
      for (p1 in exp_by_path) {
        expected = exp_by_path[p1];
        status = vc.OK;
        got = got_by_path[p1];
        if ((got == null) && (expected.item_type === item_types.DIR)) {
          status = vc.MISSING_DIR;
          msg = 'directory is missing';
        } else if (got == null) {
          status = vc.MISSING_FILE;
          msg = 'file is missing';
        } else if ((expected.item_type === item_types.SYMLINK) && (got.item_type === item_types.FILE) && (expected.link === got._possible_win_link)) {
          status = vc.ALT_SYMLINK_MATCH;
          msg = 'symlink matches file contents';
        } else if ((expected.item_type === item_types.FILE) && (got.item_type === item_types.SYMLINK) && this._hash_alt_match(expected.hash, got._link_hash)) {
          status = vc.ALT_SYMLINK_MATCH;
          msg = 'symlink matches file contents';
        } else if (expected.item_type !== got.item_type) {
          status = vc.WRONG_ITEM_TYPE;
          msg = "expected a " + (utils.item_type_name(expected.item_type)) + ", got a " + (utils.item_type_name(got.item_type));
        } else if ((expected.item_type === item_types.FILE) && (expected.exec !== got.exec)) {
          status = vc.WRONG_EXEC_PRIVS;
          msg = "execution privileges (got exec=" + got.exec + ")";
        } else if (expected.link !== got.link) {
          status = vc.WRONG_SYMLINK;
          msg = "expected symlink to `" + expected.link + "` but got `" + got.link + "`";
        } else if (!this._hash_alt_match(got.hash, expected.hash)) {
          status = vc.HASH_MISMATCH;
          msg = "contents mismatch (expected " + expected.hash.hash.slice(0, 8) + ", got " + got.hash.hash.slice(0, 8) + "...)";
        } else if (!this._hash_match(got.hash, expected.hash)) {
          status = vc.ALT_HASH_MATCH;
          msg = 'hash matches when disregarding CRLF\'s';
        }
        if (status !== vc.OK) {
          probs.push([
            status, {
              msg: msg,
              got: got || null,
              expected: expected || null
            }
          ]);
        }
      }
      for (p1 in got_by_path) {
        got = got_by_path[p1];
        if (exp_by_path[p1] == null) {
          if (got.item_type === item_types.DIR) {
            probs.push([
              vc.ORPHAN_DIR, {
                msg: 'unknown dir found',
                got: got,
                expected: null
              }
            ]);
          } else {
            probs.push([
              vc.ORPHAN_FILE, {
                msg: 'unknown file found',
                got: got,
                expected: null
              }
            ]);
          }
        }
      }
      probs.sort(function(a, b) {
        return a[0] - b[0];
      });
      return cb(probs);
    };

    CodeSign.prototype._create_presets = function() {
      var p, _i, _len, _ref;
      _ref = this.opts.presets;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        p = _ref[_i];
        switch (p) {
          case 'git':
            this.presets.push(new GitPreset());
            break;
          case 'dropbox':
            this.presets.push(new DropboxPreset());
            break;
          case 'kb':
            this.presets.push(new KbPreset());
            break;
          case 'none':
            continue;
          default:
            throw new Error("Unknown preset: " + p);
        }
      }
      if (this.opts.ignore.length) {
        return this.presets.push(new GlobberPreset(this.root_dir, this.opts.ignore));
      }
    };

    return CodeSign;

  })();

  exports.CodeSign = CodeSign;

}).call(this);
