// Generated by IcedCoffeeScript 1.7.1-g
(function() {
  var Base, E, Flat, FlatMemory, Lock, Memory, iced, log, make_esc, __iced_k, __iced_k_noop,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

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

  log = require('iced-logger');

  E = require('./err').E;

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

  Lock = require('iced-lock').Lock;

  exports.Base = Base = (function() {
    function Base() {
      this.lock = new Lock;
    }

    Base.prototype.unimplemented = function(n, cb) {
      return cb(new E.UnimplementedError("BaseKvStore::" + n + ": unimplemented"));
    };

    Base.prototype.open = function(opts, cb) {
      return this.unimplemented('open', cb);
    };

    Base.prototype.nuke = function(opts, cb) {
      return this.unimplemented('nuke', cb);
    };

    Base.prototype.close = function(opts, cb) {
      return this.unimplemented('close', cb);
    };

    Base.prototype._put = function(_arg, cb) {
      var key, value;
      key = _arg.key, value = _arg.value;
      return this.unimplemented('_put', cb);
    };

    Base.prototype._get = function(_arg, cb) {
      var key;
      key = _arg.key;
      return this.unimplemented("_get", cb);
    };

    Base.prototype._resolve = function(_arg, cb) {
      var name;
      name = _arg.name;
      return this.unimplemented("_resolve", cb);
    };

    Base.prototype._link = function(_arg, cb) {
      var key, name;
      name = _arg.name, key = _arg.key;
      return this.unimplemented('_link', cb);
    };

    Base.prototype._unlink = function(_arg, cb) {
      var name;
      name = _arg.name;
      return this.unimplemented('_unlink', cb);
    };

    Base.prototype._unlink_all = function(_arg, cb) {
      var key;
      key = _arg.key;
      return this.unimplemented('_unlink_all', cb);
    };

    Base.prototype._remove = function(_arg, cb) {
      var key;
      key = _arg.key;
      return this.unimplemented('_remove', cb);
    };

    Base.prototype.make_kvstore_key = function(_arg) {
      var key, type;
      type = _arg.type, key = _arg.key;
      type || (type = key.slice(-2));
      return [type, key].join(":").toLowerCase();
    };

    Base.prototype.make_lookup_name = function(_arg) {
      var name, type;
      type = _arg.type, name = _arg.name;
      return [type, name].join(":").toLowerCase();
    };

    Base.prototype.unmake_kvstore_key = function(_arg) {
      var key, parts;
      key = _arg.key;
      parts = key.split(":");
      return {
        type: parts[0],
        key: parts.slice(1).join(":")
      };
    };

    Base.prototype.can_unlink = function() {
      return true;
    };

    Base.prototype.link = function(_arg, cb) {
      var key, name, type;
      type = _arg.type, name = _arg.name, key = _arg.key;
      return this._link({
        name: this.make_lookup_name({
          type: type,
          name: name
        }),
        key: this.make_kvstore_key({
          key: key,
          type: type
        })
      }, cb);
    };

    Base.prototype.unlink = function(_arg, cb) {
      var name, type;
      type = _arg.type, name = _arg.name;
      return this._unlink({
        name: this.make_lookup_name({
          type: type,
          name: name
        })
      }, cb);
    };

    Base.prototype.unlink_all = function(_arg, cb) {
      var key, type;
      type = _arg.type, key = _arg.key;
      return this._unlink_all({
        key: this.make_kvstore_key({
          type: type,
          key: key
        })
      }, cb);
    };

    Base.prototype.get = function(_arg, cb) {
      var key, type;
      type = _arg.type, key = _arg.key;
      return this._get({
        key: this.make_kvstore_key({
          type: type,
          key: key
        })
      }, cb);
    };

    Base.prototype.resolve = function(_arg, cb) {
      var err, key, name, type, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      type = _arg.type, name = _arg.name;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
            funcname: "Base.resolve"
          });
          _this._resolve({
            name: _this.make_lookup_name({
              type: type,
              name: name
            })
          }, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                err = arguments[0];
                return key = arguments[1];
              };
            })(),
            lineno: 55
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          if ((typeof err === "undefined" || err === null) && (typeof key !== "undefined" && key !== null)) {
            key = _this.unmake_kvstore_key({
              key: key
            }).key;
          }
          return cb(err, key);
        };
      })(this));
    };

    Base.prototype.put = function(_arg, cb) {
      var esc, key, kvsk, name, names, type, value, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      type = _arg.type, key = _arg.key, value = _arg.value, name = _arg.name, names = _arg.names;
      esc = make_esc(cb, "BaseKvStore::put");
      kvsk = this.make_kvstore_key({
        type: type,
        key: key
      });
      log.debug("+ KvStore::put " + key + "/" + kvsk);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
            funcname: "Base.put"
          });
          _this._put({
            key: kvsk,
            value: value
          }, esc(__iced_deferrals.defer({
            lineno: 66
          })));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          if ((name != null) && (names == null)) {
            names = [name];
          }
          (function(__iced_k) {
            if (names && names.length) {
              (function(__iced_k) {
                var _i, _len, _ref, _results, _while;
                _ref = names;
                _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 {
                    name = _ref[_i];
                    log.debug("| KvStore::link " + name + " -> " + key);
                    (function(__iced_k) {
                      __iced_deferrals = new iced.Deferrals(__iced_k, {
                        parent: ___iced_passed_deferral,
                        filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
                        funcname: "Base.put"
                      });
                      _this.link({
                        type: type,
                        name: name,
                        key: key
                      }, esc(__iced_deferrals.defer({
                        lineno: 71
                      })));
                      __iced_deferrals._fulfill();
                    })(_next);
                  }
                };
                _while(__iced_k);
              })(__iced_k);
            } else {
              return __iced_k();
            }
          })(function() {
            log.debug("- KvStore::put " + key + " -> ok");
            return cb(null);
          });
        };
      })(this));
    };

    Base.prototype.remove = function(_arg, cb) {
      var err, k, key, optional, type, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      type = _arg.type, key = _arg.key, optional = _arg.optional;
      k = this.make_kvstore_key({
        type: type,
        key: key
      });
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
            funcname: "Base.remove"
          });
          _this.lock.acquire(__iced_deferrals.defer({
            lineno: 79
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          log.debug("+ DB remove " + key + "/" + k);
          (function(__iced_k) {
            __iced_deferrals = new iced.Deferrals(__iced_k, {
              parent: ___iced_passed_deferral,
              filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
              funcname: "Base.remove"
            });
            _this._remove({
              key: k
            }, __iced_deferrals.defer({
              assign_fn: (function() {
                return function() {
                  return err = arguments[0];
                };
              })(),
              lineno: 83
            }));
            __iced_deferrals._fulfill();
          })(function() {
            (function(__iced_k) {
              if ((typeof err !== "undefined" && err !== null) && (err instanceof E.NotFoundError) && optional) {
                log.debug("| No object found for " + k);
                return __iced_k(err = null);
              } else {
                (function(__iced_k) {
                  if (err == null) {
                    (function(__iced_k) {
                      __iced_deferrals = new iced.Deferrals(__iced_k, {
                        parent: ___iced_passed_deferral,
                        filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
                        funcname: "Base.remove"
                      });
                      _this._unlink_all({
                        type: type,
                        key: k
                      }, __iced_deferrals.defer({
                        assign_fn: (function() {
                          return function() {
                            return err = arguments[0];
                          };
                        })(),
                        lineno: 88
                      }));
                      __iced_deferrals._fulfill();
                    })(__iced_k);
                  } else {
                    return __iced_k();
                  }
                })(__iced_k);
              }
            })(function() {
              log.debug("- DB remove " + key + "/" + k + " -> " + (typeof err !== "undefined" && err !== null ? 'ok' : void 0));
              _this.lock.release();
              return cb(err);
            });
          });
        };
      })(this));
    };

    Base.prototype.lookup = function(_arg, cb) {
      var esc, key, name, type, value, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      type = _arg.type, name = _arg.name;
      esc = make_esc(cb, "BaseKvStore::lookup");
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
            funcname: "Base.lookup"
          });
          _this.resolve({
            name: name,
            type: type
          }, esc(__iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return key = arguments[0];
              };
            })(),
            lineno: 99
          })));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          (function(__iced_k) {
            __iced_deferrals = new iced.Deferrals(__iced_k, {
              parent: ___iced_passed_deferral,
              filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
              funcname: "Base.lookup"
            });
            _this.get({
              type: type,
              key: key
            }, esc(__iced_deferrals.defer({
              assign_fn: (function() {
                return function() {
                  return value = arguments[0];
                };
              })(),
              lineno: 100
            })));
            __iced_deferrals._fulfill();
          })(function() {
            return cb(null, value);
          });
        };
      })(this));
    };

    return Base;

  })();

  exports.Flat = Flat = (function(_super) {
    __extends(Flat, _super);

    function Flat() {
      return Flat.__super__.constructor.apply(this, arguments);
    }

    Flat.prototype.make_kvstore_key = function(_arg) {
      var key, type;
      type = _arg.type, key = _arg.key;
      return "kv:" + Flat.__super__.make_kvstore_key.call(this, {
        type: type,
        key: key
      });
    };

    Flat.prototype.make_lookup_name = function(_arg) {
      var name, type;
      type = _arg.type, name = _arg.name;
      return "lo:" + Flat.__super__.make_lookup_name.call(this, {
        type: type,
        name: name
      });
    };

    Flat.prototype.unmake_kvstore_key = function(_arg) {
      var key, parts;
      key = _arg.key;
      parts = key.split(":");
      return {
        type: parts[1],
        key: parts.slice(2).join(":")
      };
    };

    Flat.prototype._link = function(_arg, cb) {
      var err, key, name, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      key = _arg.key, name = _arg.name;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
            funcname: "Flat._link"
          });
          _this._put({
            key: name,
            value: key
          }, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return err = arguments[0];
              };
            })(),
            lineno: 122
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb(err);
        };
      })(this));
    };

    Flat.prototype._unlink = function(_arg, cb) {
      var err, name, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      name = _arg.name;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
            funcname: "Flat._unlink"
          });
          _this._remove({
            key: name
          }, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return err = arguments[0];
              };
            })(),
            lineno: 126
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb(err);
        };
      })(this));
    };

    Flat.prototype._unlink_all = function(_arg, cb) {
      var key;
      key = _arg.key;
      log.debug("| Can't _unlink_all names for " + key + " in flat kvstore");
      return cb(null);
    };

    Flat.prototype._resolve = function(_arg, cb) {
      var err, name, value, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      name = _arg.name;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/home/jacko/libkeybase-js/src/kvstore.iced",
            funcname: "Flat._resolve"
          });
          _this._get({
            key: name
          }, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                err = arguments[0];
                return value = arguments[1];
              };
            })(),
            lineno: 134
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          if ((typeof err !== "undefined" && err !== null) && (err instanceof E.NotFoundError)) {
            err = new E.LookupNotFoundError("No lookup available for " + name);
          }
          return cb(err, value);
        };
      })(this));
    };

    Flat.prototype.can_unlink = function() {
      return false;
    };

    return Flat;

  })(Base);

  exports.Memory = Memory = (function(_super) {
    __extends(Memory, _super);

    function Memory() {
      Memory.__super__.constructor.apply(this, arguments);
      this.data = {
        lookup: {},
        rlookup: {},
        kv: {}
      };
    }

    Memory.prototype.open = function(opts, cb) {
      return cb(null);
    };

    Memory.prototype.nuke = function(opts, cb) {
      return cb(null);
    };

    Memory.prototype.close = function(opts, cb) {
      return cb(null);
    };

    Memory.prototype._put = function(_arg, cb) {
      var key, value;
      key = _arg.key, value = _arg.value;
      this.data.kv[key] = value;
      return cb(null);
    };

    Memory.prototype._get = function(_arg, cb) {
      var err, key, val;
      key = _arg.key;
      err = null;
      if ((val = this.data.kv[key]) === void 0) {
        err = new E.NotFoundError("key not found: '" + key + "'");
      }
      return cb(err, val);
    };

    Memory.prototype._resolve = function(_arg, cb) {
      var err, key, name;
      name = _arg.name;
      err = null;
      if ((key = this.data.lookup[name]) == null) {
        err = new E.LookupNotFoundError("name not found: '" + name + "'");
      }
      return cb(err, key);
    };

    Memory.prototype._link = function(_arg, cb) {
      var key, name, set;
      key = _arg.key, name = _arg.name;
      this.data.lookup[name] = key;
      if ((set = this.data.rlookup[key]) == null) {
        this.data.rlookup[key] = set = {};
      }
      set[name] = true;
      return cb(null);
    };

    Memory.prototype._unlink = function(_arg, cb) {
      var d, err, key, name;
      name = _arg.name;
      if ((key = this.data.lookup[name]) != null) {
        if ((d = this.data.rlookup[key]) != null) {
          delete d[name];
        }
        delete this.data.lookup[name];
        err = null;
      } else {
        err = new E.LookupNotFoundError("cannot unlink '" + name + "'");
      }
      return cb(err);
    };

    Memory.prototype._remove = function(_arg, cb) {
      var err, key, v;
      key = _arg.key;
      err = null;
      if ((v = this.data.kv[key]) == null) {
        err = new E.NotFoundError("key not found: '" + key + "'");
      } else {
        delete this.data.kv[key];
      }
      return cb(err);
    };

    Memory.prototype._unlink_all = function(_arg, cb) {
      var d, err, key, name, _;
      key = _arg.key;
      if ((d = this.data.rlookup[key]) != null) {
        for (name in d) {
          _ = d[name];
          delete this.data.lookup[name];
        }
        delete this.data.rlookup[key];
        err = null;
      } else {
        err = new E.LookupNotFoundError("cannot find names for key '" + key + "'");
      }
      return cb(err);
    };

    return Memory;

  })(Base);

  exports.FlatMemory = FlatMemory = (function(_super) {
    __extends(FlatMemory, _super);

    function FlatMemory() {
      FlatMemory.__super__.constructor.apply(this, arguments);
      this.kv = {};
    }

    FlatMemory.prototype.open = function(opts, cb) {
      return cb(null);
    };

    FlatMemory.prototype.nuke = function(opts, cb) {
      return cb(null);
    };

    FlatMemory.prototype.close = function(opts, cb) {
      return cb(null);
    };

    FlatMemory.prototype._put = function(_arg, cb) {
      var key, value;
      key = _arg.key, value = _arg.value;
      this.kv[key] = value;
      return cb(null);
    };

    FlatMemory.prototype._get = function(_arg, cb) {
      var err, key, val;
      key = _arg.key;
      err = null;
      if ((val = this.kv[key]) === void 0) {
        err = new E.NotFoundError("key not found: '" + key + "'");
      }
      return cb(err, val);
    };

    FlatMemory.prototype._remove = function(_arg, cb) {
      var err, key, v;
      key = _arg.key;
      err = null;
      if ((v = this.kv[key]) == null) {
        err = new E.NotFoundError("key not found: '" + key + "'");
      } else {
        delete this.kv[key];
      }
      return cb(err);
    };

    return FlatMemory;

  })(Flat);

}).call(this);
