'use strict';

var Block = require('ipfs-block');
var mDAG = require('ipfs-merkle-dag');
var DAGNode = mDAG.DAGNode;

module.exports = function object(self) {
  return {
    new: function _new(template, callback) {
      if (!callback) {
        callback = template;
      }
      var node = new DAGNode();
      var block = new Block(node.marshal());
      self._blockS.addBlock(block, function (err) {
        if (err) {
          return callback(err);
        }
        callback(null, {
          Hash: block.key,
          Size: node.size(),
          Name: ''
        });
      });
    },
    patch: {
      appendData: function appendData(multihash, data, callback) {
        self.object.get(multihash, function (err, obj) {
          if (err) {
            return callback(err);
          }
          obj.data = Buffer.concat([obj.data, data]);
          self._dagS.add(obj, function (err) {
            if (err) {
              return callback(err);
            }
            callback(null, obj);
          });
        });
      },
      addLink: function addLink(multihash, link, callback) {
        self.object.get(multihash, function (err, obj) {
          if (err) {
            return callback(err);
          }
          obj.addRawLink(link);
          self._dagS.add(obj, function (err) {
            if (err) {
              return callback(err);
            }
            callback(null, obj);
          });
        });
      },
      rmLink: function rmLink(multihash, linkRef, callback) {
        self.object.get(multihash, function (err, obj) {
          if (err) {
            return callback(err);
          }
          obj.links = obj.links.filter(function (link) {
            // filter by name when linkRef is a string, or by hash otherwise
            if (typeof linkRef === 'string') {
              return link.name !== linkRef;
            }
            return !link.hash.equals(linkRef);
          });
          self._dagS.add(obj, function (err) {
            if (err) {
              return callback(err);
            }
            callback(null, obj);
          });
        });
      },
      setData: function setData(multihash, data, callback) {
        self.object.get(multihash, function (err, obj) {
          if (err) {
            return callback(err);
          }
          obj.data = data;
          self._dagS.add(obj, function (err) {
            if (err) {
              return callback(err);
            }
            callback(null, obj);
          });
        });
      }
    },
    data: function data(multihash, callback) {
      self.object.get(multihash, function (err, obj) {
        if (err) {
          return callback(err);
        }
        callback(null, obj.data);
      });
    },
    links: function links(multihash, callback) {
      self.object.get(multihash, function (err, obj) {
        if (err) {
          return callback(err);
        }
        callback(null, obj.links);
      });
    },
    get: function get(multihash, options, callback) {
      if (typeof options === 'function') {
        callback = options;
        options = {};
      }
      self._dagS.get(multihash, callback);
    },
    put: function put(dagNode, options, callback) {
      if (typeof options === 'function') {
        callback = options;
        options = {};
      }
      self._dagS.add(dagNode, callback);
    },
    stat: function stat(multihash, options, callback) {
      if (typeof options === 'function') {
        callback = options;
        options = {};
      }

      self.object.get(multihash, function (err, obj) {
        if (err) {
          return callback(err);
        }
        var res = {
          NumLinks: obj.links.length,
          BlockSize: obj.marshal().length,
          LinksSize: obj.links.reduce(function (prev, link) {
            return prev + link.size;
          }, 0),
          DataSize: obj.data.length,
          CumulativeSize: ''
        };
        callback(null, res);
      });
    }
  };
};