// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var DB, E, a_json_parse, athrow, createHash, fs, hash, iced, iutils, make_esc, mkdir_p, mkdir_p_2, path, rm_r, __iced_k, __iced_k_noop, _ref, _ref1;

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

  createHash = require('crypto').createHash;

  iutils = require('iced-utils');

  _ref = iutils.fs, mkdir_p = _ref.mkdir_p, rm_r = _ref.rm_r;

  _ref1 = iutils.util, athrow = _ref1.athrow, a_json_parse = _ref1.a_json_parse;

  fs = require('fs');

  path = require('path');

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

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

  hash = function(x) {
    var h;
    h = createHash('SHA256');
    h.update(x);
    return h.digest().toString('hex');
  };

  mkdir_p_2 = function(_arg, cb) {
    var cwd, dirs, err, made, mode, p, root, so, ___iced_passed_deferral, __iced_deferrals, __iced_k;
    __iced_k = __iced_k_noop;
    ___iced_passed_deferral = iced.findDeferral(arguments);
    root = _arg.root, dirs = _arg.dirs, mode = _arg.mode;
    err = null;
    made = 0;
    cwd = root;
    (function(_this) {
      return (function(__iced_k) {
        var _i, _len, _ref2, _results, _while;
        _ref2 = dirs;
        _len = _ref2.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 = _ref2[_i];
            if (err == null) {
              cwd = [cwd, p].join(path.sep);
              (function(__iced_k) {
                __iced_deferrals = new iced.Deferrals(__iced_k, {
                  parent: ___iced_passed_deferral,
                  filename: "/Users/max/src/iced/iced-db/src/db.iced"
                });
                fs.stat(cwd, __iced_deferrals.defer({
                  assign_fn: (function() {
                    return function() {
                      err = arguments[0];
                      return so = arguments[1];
                    };
                  })(),
                  lineno: 25
                }));
                __iced_deferrals._fulfill();
              })(function() {
                (function(__iced_k) {
                  if ((err != null) && (err.code === 'ENOENT')) {
                    (function(__iced_k) {
                      __iced_deferrals = new iced.Deferrals(__iced_k, {
                        parent: ___iced_passed_deferral,
                        filename: "/Users/max/src/iced/iced-db/src/db.iced"
                      });
                      fs.mkdir(cwd, mode, __iced_deferrals.defer({
                        assign_fn: (function() {
                          return function() {
                            return err = arguments[0];
                          };
                        })(),
                        lineno: 27
                      }));
                      __iced_deferrals._fulfill();
                    })(function() {
                      return __iced_k(err == null ? made++ : void 0);
                    });
                  } else {
                    return __iced_k((err == null) && (typeof so !== "undefined" && so !== null) && !so.isDirectory() ? err = new Error("Path component " + cwd + " isn't a directory") : void 0);
                  }
                })(_next);
              });
            } else {
              return _continue();
            }
          }
        };
        _while(__iced_k);
      });
    })(this)((function(_this) {
      return function() {
        return cb(err, made);
      };
    })(this));
  };

  DB = (function() {
    function DB(_arg) {
      var dir_mode, file_mode, json, levels;
      this.root = _arg.root, levels = _arg.levels, json = _arg.json, dir_mode = _arg.dir_mode, file_mode = _arg.file_mode;
      this.levels = levels || 2;
      this.json = json != null ? json : true;
      this._path_prefix = this.root.split(path.sep);
      this.dir_mode = dir_mode || 0x1ed;
      this.file_mode = file_mode || 0x1a4;
    }

    DB.prototype._key_to_hkey = function(key) {
      return hash(key);
    };

    DB.prototype._key_to_dirs = function(key) {
      return this._hkey_to_dirs(this._key_to_hkey(key));
    };

    DB.prototype._keys_to_dirs = function(_arg) {
      var hkey, key;
      key = _arg.key, hkey = _arg.hkey;
      if (key != null) {
        return this._key_to_dirs(key);
      } else if (hkey != null) {
        return this._hkey_to_dirs(hkey);
      } else {
        return null;
      }
    };

    DB.prototype._hkey_to_dirs = function(hkey) {
      var i, j, out, _i, _ref2;
      out = [];
      for (i = _i = 0, _ref2 = this.levels; 0 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 0 <= _ref2 ? ++_i : --_i) {
        j = i * 2;
        out.push(hkey.slice(j, j + 2));
      }
      out.push(hkey);
      return out;
    };

    DB.prototype._mkpath = function(dirs) {
      var p, top, _ref2;
      top = ((_ref2 = this._path_prefix) != null ? _ref2[0] : void 0) === '' ? [path.sep] : [];
      p = top.concat(this._path_prefix).concat(dirs);
      return path.join.apply(path, p);
    };

    DB.prototype._mkpath_from_key = function(key) {
      return this._mkpath(this._key_to_dirs(key));
    };

    DB.prototype._mkpath_from_hkey = function(hkey) {
      return this._mkpath(this._hkey_to_dirs(hkey));
    };

    DB.prototype._mkpath_from_keys = function(_arg) {
      var hkey, key;
      key = _arg.key, hkey = _arg.hkey;
      if (key != null) {
        return this._mkpath_from_key(key);
      } else if (hkey != null) {
        return this._mkpath_from_hkey(hkey);
      } else {
        return null;
      }
    };

    DB.prototype.create = function(cb) {
      var err, made, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/iced/iced-db/src/db.iced",
            funcname: "DB.create"
          });
          mkdir_p(_this.root, _this.dir_mode, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                err = arguments[0];
                return made = arguments[1];
              };
            })(),
            lineno: 96
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb(err, made);
        };
      })(this));
    };

    DB.prototype.drop = function(cb) {
      var err, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/iced/iced-db/src/db.iced",
            funcname: "DB.drop"
          });
          rm_r(_this.root, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return err = arguments[0];
              };
            })(),
            lineno: 102
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb(err);
        };
      })(this));
    };

    DB.prototype.put = function(_arg, cb) {
      var dirs, encoding, err, esc, f, file, hkey, json, key, opts, typ, value, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      hkey = _arg.hkey, key = _arg.key, value = _arg.value, json = _arg.json;
      hkey || (hkey = this._key_to_hkey(key));
      dirs = this._hkey_to_dirs(hkey);
      file = dirs.pop();
      esc = make_esc(cb, "Db::put");
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/iced/iced-db/src/db.iced",
            funcname: "DB.put"
          });
          mkdir_p_2({
            root: _this.root,
            dirs: dirs,
            mode: _this.dir_mode
          }, esc(__iced_deferrals.defer({
            lineno: 113
          })));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          if ((!(json != null) && _this.json) || json) {
            value = JSON.stringify(value);
          }
          err = null;
          encoding = "binary";
          typ = typeof value;
          if (typ === 'object') {
            if (Buffer.isBuffer(value)) {
              encoding = "binary";
            } else {
              err = new Error("Cannot put object");
            }
          } else if (typ === 'string') {
            value = new Buffer(value, 'utf8');
            encoding = "utf8";
          } else {
            err = new Error("Cannot put value of type: " + typ);
          }
          (function(__iced_k) {
            if (err != null) {
              (function(__iced_k) {
                __iced_deferrals = new iced.Deferrals(__iced_k, {
                  parent: ___iced_passed_deferral,
                  filename: "/Users/max/src/iced/iced-db/src/db.iced",
                  funcname: "DB.put"
                });
                athrow(err, esc(__iced_deferrals.defer({
                  lineno: 133
                })));
                __iced_deferrals._fulfill();
              })(__iced_k);
            } else {
              return __iced_k();
            }
          })(function() {
            f = _this._mkpath(dirs.concat([file]));
            opts = {
              encoding: encoding,
              mode: _this.file_mode
            };
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/iced/iced-db/src/db.iced",
                funcname: "DB.put"
              });
              fs.writeFile(f, value, opts, esc(__iced_deferrals.defer({
                lineno: 137
              })));
              __iced_deferrals._fulfill();
            })(function() {
              return cb(err, {
                hkey: hkey
              });
            });
          });
        };
      })(this));
    };

    DB.prototype.get = function(_arg, cb) {
      var buf, err, f, hkey, json, key, value, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      hkey = _arg.hkey, key = _arg.key, json = _arg.json;
      value = null;
      err = null;
      f = this._mkpath_from_keys({
        key: key,
        hkey: hkey
      });
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/iced/iced-db/src/db.iced",
            funcname: "DB.get"
          });
          fs.readFile(f, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                err = arguments[0];
                return buf = arguments[1];
              };
            })(),
            lineno: 147
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          (function(__iced_k) {
            if (err != null) {
              return __iced_k(err.code === 'ENOENT' ? err = new E.NotFoundError("No data for key " + key) : void 0);
            } else {
              (function(__iced_k) {
                if ((!(json != null) && _this.json) || json) {
                  (function(__iced_k) {
                    __iced_deferrals = new iced.Deferrals(__iced_k, {
                      parent: ___iced_passed_deferral,
                      filename: "/Users/max/src/iced/iced-db/src/db.iced",
                      funcname: "DB.get"
                    });
                    a_json_parse(buf, __iced_deferrals.defer({
                      assign_fn: (function() {
                        return function() {
                          err = arguments[0];
                          return value = arguments[1];
                        };
                      })(),
                      lineno: 152
                    }));
                    __iced_deferrals._fulfill();
                  })(function() {
                    return __iced_k(err != null ? err = new E.DecodeError(err.message) : void 0);
                  });
                } else {
                  return __iced_k(value = buf);
                }
              })(__iced_k);
            }
          })(function() {
            return cb(err, value);
          });
        };
      })(this));
    };

    DB.prototype.del = function(_arg, cb) {
      var err, f, hkey, key, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      key = _arg.key, hkey = _arg.hkey;
      f = this._mkpath_from_keys({
        key: key,
        hkey: hkey
      });
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/iced/iced-db/src/db.iced",
            funcname: "DB.del"
          });
          fs.unlink(f, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return err = arguments[0];
              };
            })(),
            lineno: 163
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          if ((typeof err !== "undefined" && err !== null) && err.code === 'ENOENT') {
            err = new E.NotFoundError("No data for key " + key);
          }
          return cb(err);
        };
      })(this));
    };

    return DB;

  })();

  exports.DB = DB;

}).call(this);
