var encodings = require('./lib/encodings');

module.exports = Codec;

function Codec(opts){
  this.opts = opts || {};
  this.encodings = encodings;
}

Codec.prototype._encoding = function(encoding){
  if (typeof encoding == 'string') encoding = encodings[encoding];
  if (!encoding) encoding = encodings.id;
  return encoding;
};

Codec.prototype._keyEncoding = function(opts, batchOpts){
  return this._encoding(batchOpts && batchOpts.keyEncoding
    || opts && opts.keyEncoding
    || this.opts.keyEncoding);
};

Codec.prototype._valueEncoding = function(opts, batchOpts){
  return this._encoding(
    batchOpts && (batchOpts.valueEncoding || batchOpts.encoding)
    || opts && (opts.valueEncoding || opts.encoding)
    || (this.opts.valueEncoding || this.opts.encoding));
};

Codec.prototype.encodeKey = function(key, opts, batchOpts){
  return this._keyEncoding(opts, batchOpts).encode(key);
};

Codec.prototype.encodeValue = function(value, opts, batchOpts){
  return this._valueEncoding(opts, batchOpts).encode(value);
};

Codec.prototype.decodeKey = function(key, opts){
  return this._keyEncoding(opts).decode(key);
};

Codec.prototype.decodeValue = function(value, opts){
  return this._valueEncoding(opts).decode(value);
};

Codec.prototype.encodeBatch = function(ops, opts){
  var self = this;

  return ops.map(function(_op){
    var op = {
      type: _op.type,
      key: self.encodeKey(_op.key, opts, _op)
    };
    if (self.keyAsBuffer(opts, _op)) op.keyEncoding = 'binary';
    if (_op.prefix) op.prefix = _op.prefix;
    if ('value' in _op) {
      op.value = self.encodeValue(_op.value, opts, _op);
      if (self.valueAsBuffer(opts, _op)) op.valueEncoding = 'binary';
    }
    return op;
  });
};

var ltgtKeys = ['lt', 'gt', 'lte', 'gte', 'start', 'end'];

Codec.prototype.encodeLtgt = function(ltgt){
  var self = this;
  var ret = {};
  Object.keys(ltgt).forEach(function(key){
    ret[key] = ltgtKeys.indexOf(key) > -1
      ? self.encodeKey(ltgt[key], ltgt)
      : ltgt[key]
  });
  return ret;
};

Codec.prototype.createStreamDecoder = function(opts){
  var self = this;

  if (opts.keys && opts.values) {
    return function(key, value){
      return {
        key: self.decodeKey(key, opts),
        value: self.decodeValue(value, opts)
      };
    };
  } else if (opts.keys) {
    return function(key) {
      return self.decodeKey(key, opts);
    }; 
  } else if (opts.values) {
    return function(_, value){
      return self.decodeValue(value, opts);
    }
  } else {
    return function(){};
  }
};

Codec.prototype.keyAsBuffer = function(opts){
  return this._keyEncoding(opts).buffer;
};

Codec.prototype.valueAsBuffer = function(opts){
  return this._valueEncoding(opts).buffer;
};

