'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var dagPB = require('@ipld/dag-pb');
var chai_js = require('aegir/utils/chai.js');
var mocha = require('../utils/mocha.js');
var testTimeout = require('../utils/test-timeout.js');
var fromString = require('uint8arrays/from-string');

function _interopNamespace(e) {
  if (e && e.__esModule) return e;
  var n = Object.create(null);
  if (e) {
    Object.keys(e).forEach(function (k) {
      if (k !== 'default') {
        var d = Object.getOwnPropertyDescriptor(e, k);
        Object.defineProperty(n, k, d.get ? d : {
          enumerable: true,
          get: function () { return e[k]; }
        });
      }
    });
  }
  n["default"] = e;
  return Object.freeze(n);
}

var dagPB__namespace = /*#__PURE__*/_interopNamespace(dagPB);

function testResolve(factory, options) {
  const describe = mocha.getDescribe(options);
  const it = mocha.getIt(options);
  describe('.dag.resolve', () => {
    let ipfs;
    before(async () => {
      ipfs = (await factory.spawn()).api;
    });
    after(() => factory.clean());
    it('should respect timeout option when resolving a path within a DAG node', async () => {
      const cid = await ipfs.dag.put({}, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      return testTimeout(() => ipfs.dag.resolve(cid, { timeout: 1 }));
    });
    it('should resolve a path inside a cbor node', async () => {
      const obj = {
        a: 1,
        b: [
          1,
          2,
          3
        ],
        c: {
          ca: [
            5,
            6,
            7
          ],
          cb: 'foo'
        }
      };
      const cid = await ipfs.dag.put(obj, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.resolve(`${ cid }/c/cb`);
      chai_js.expect(result).to.have.deep.property('cid', cid);
      chai_js.expect(result).to.have.property('remainderPath', 'c/cb');
    });
    it('should resolve a path inside a cbor node by CID', async () => {
      const obj = {
        a: 1,
        b: [
          1,
          2,
          3
        ],
        c: {
          ca: [
            5,
            6,
            7
          ],
          cb: 'foo'
        }
      };
      const cid = await ipfs.dag.put(obj, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.resolve(cid, { path: '/c/cb' });
      chai_js.expect(result).to.have.deep.property('cid', cid);
      chai_js.expect(result).to.have.property('remainderPath', 'c/cb');
    });
    it('should resolve a multi-node path inside a cbor node', async () => {
      const obj0 = {
        ca: [
          5,
          6,
          7
        ],
        cb: 'foo'
      };
      const cid0 = await ipfs.dag.put(obj0, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      const obj1 = {
        a: 1,
        b: [
          1,
          2,
          3
        ],
        c: cid0
      };
      const cid1 = await ipfs.dag.put(obj1, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.resolve(`/ipfs/${ cid1 }/c/cb`);
      chai_js.expect(result).to.have.deep.property('cid', cid0);
      chai_js.expect(result).to.have.property('remainderPath', 'cb');
    });
    it('should resolve a multi-node path inside a cbor node by CID', async () => {
      const obj0 = {
        ca: [
          5,
          6,
          7
        ],
        cb: 'foo'
      };
      const cid0 = await ipfs.dag.put(obj0, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      const obj1 = {
        a: 1,
        b: [
          1,
          2,
          3
        ],
        c: cid0
      };
      const cid1 = await ipfs.dag.put(obj1, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.resolve(cid1, { path: '/c/cb' });
      chai_js.expect(result).to.have.deep.property('cid', cid0);
      chai_js.expect(result).to.have.property('remainderPath', 'cb');
    });
    it('should resolve a raw node', async () => {
      const node = fromString.fromString('hello world');
      const cid = await ipfs.dag.put(node, {
        storeCodec: 'raw',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.resolve(cid, { path: '/' });
      chai_js.expect(result).to.have.deep.property('cid', cid);
      chai_js.expect(result).to.have.property('remainderPath', '');
    });
    it('should resolve a path inside a dag-pb node linked to from another dag-pb node', async () => {
      const someData = fromString.fromString('some other data');
      const childNode = {
        Data: someData,
        Links: []
      };
      const childCid = await ipfs.dag.put(childNode, {
        storeCodec: 'dag-pb',
        hashAlg: 'sha2-256'
      });
      const linkToChildNode = {
        Name: 'foo',
        Tsize: dagPB__namespace.encode(childNode).length,
        Hash: childCid
      };
      const parentNode = {
        Data: fromString.fromString('derp'),
        Links: [linkToChildNode]
      };
      const parentCid = await ipfs.dag.put(parentNode, {
        storeCodec: 'dag-pb',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.resolve(parentCid, { path: '/foo' });
      chai_js.expect(result).to.have.deep.property('cid', childCid);
      chai_js.expect(result).to.have.property('remainderPath', '');
    });
  });
}

exports.testResolve = testResolve;
