'use strict';

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

var fromString = require('uint8arrays/from-string');
var dagPB = require('@ipld/dag-pb');
var dagCBOR = require('@ipld/dag-cbor');
var dagJOSE = require('dag-jose');
var ipfsUnixfsImporter = require('ipfs-unixfs-importer');
var ipfsUnixfs = require('ipfs-unixfs');
var all = require('it-all');
var cid = require('multiformats/cid');
var sha2 = require('multiformats/hashes/sha2');
var base32 = require('multiformats/bases/base32');
var base64 = require('multiformats/bases/base64');
var chai_js = require('aegir/utils/chai.js');
var mocha = require('../utils/mocha.js');
var testTimeout = require('../utils/test-timeout.js');
var identity = require('multiformats/hashes/identity');
var blockstoreAdapter = require('../utils/blockstore-adapter.js');
var didJwt = require('did-jwt');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

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);
var dagCBOR__namespace = /*#__PURE__*/_interopNamespace(dagCBOR);
var dagJOSE__namespace = /*#__PURE__*/_interopNamespace(dagJOSE);
var all__default = /*#__PURE__*/_interopDefaultLegacy(all);

function testGet(factory, options) {
  const describe = mocha.getDescribe(options);
  const it = mocha.getIt(options);
  describe('.dag.get', () => {
    let ipfs;
    before(async () => {
      ipfs = (await factory.spawn()).api;
    });
    after(() => factory.clean());
    let pbNode;
    let cborNode;
    let joseNode;
    let nodePb;
    let nodeCbor;
    let nodeJose;
    let cidPb;
    let cidCbor;
    let cidJose;
    before(async () => {
      const someData = fromString.fromString('some other data');
      pbNode = {
        Data: someData,
        Links: []
      };
      cborNode = { data: someData };
      joseNode = {
        protected: 'eyJhbGciOiJkaXIiLCJlbmMiOiJYQzIwUCJ9',
        iv: 'DhVb9URR_o_85MOl-hCellwPTtQ_dj6d',
        ciphertext: 'EtUsNJcKzEKdFM9DW5Ua5tVyaQRCKsAD',
        tag: '-vG17pRSVB2Vycf2MZRgBA'
      };
      nodePb = {
        Data: fromString.fromString('I am inside a Protobuf'),
        Links: []
      };
      cidPb = cid.CID.createV1(dagPB__namespace.code, await sha2.sha256.digest(dagPB__namespace.encode(nodePb)));
      nodeCbor = {
        someData: 'I am inside a Cbor object',
        pb: cidPb
      };
      cidCbor = cid.CID.createV1(dagCBOR__namespace.code, await sha2.sha256.digest(dagCBOR__namespace.encode(nodeCbor)));
      await ipfs.dag.put(nodePb, {
        storeCodec: 'dag-pb',
        hashAlg: 'sha2-256'
      });
      await ipfs.dag.put(nodeCbor, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      const signer = didJwt.ES256KSigner('278a5de700e29faae8e40e366ec5012b5ec63d36ec77e8a2417154cc1d25383f');
      nodeJose = await didJwt.createJWS(base64.base64url.encode(cidCbor.bytes).slice(1), signer);
      cidJose = cid.CID.createV1(dagJOSE__namespace.code, await sha2.sha256.digest(dagJOSE__namespace.encode(nodeJose)));
      await ipfs.dag.put(nodeJose, {
        storeCodec: dagJOSE__namespace.name,
        hashAlg: 'sha2-256'
      });
    });
    it('should respect timeout option when getting a DAG node', () => {
      return testTimeout(() => ipfs.dag.get(cid.CID.parse('QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAd'), { timeout: 1 }));
    });
    it('should get a dag-pb node', async () => {
      const cid = await ipfs.dag.put(pbNode, {
        storeCodec: 'dag-pb',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.get(cid);
      const node = result.value;
      chai_js.expect(pbNode).to.eql(node);
    });
    it('should get a dag-cbor node', async () => {
      const cid = await ipfs.dag.put(cborNode, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.get(cid);
      const node = result.value;
      chai_js.expect(cborNode).to.eql(node);
    });
    it('should get a dag-pb node with path', async () => {
      const result = await ipfs.dag.get(cidPb, { path: '/' });
      const node = result.value;
      const cid$1 = cid.CID.createV1(dagPB__namespace.code, await sha2.sha256.digest(dagPB__namespace.encode(node)));
      chai_js.expect(cid$1.equals(cidPb)).to.be.true();
    });
    it('should get a dag-pb node local value', async function () {
      const result = await ipfs.dag.get(cidPb, { path: 'Data' });
      chai_js.expect(result.value).to.eql(fromString.fromString('I am inside a Protobuf'));
    });
    it.skip('should get a dag-pb node value one level deep', done => {
    });
    it.skip('should get a dag-pb node value two levels deep', done => {
    });
    it('should get a dag-cbor node with path', async () => {
      const result = await ipfs.dag.get(cidCbor, { path: '/' });
      const node = result.value;
      const cid$1 = cid.CID.createV1(dagCBOR__namespace.code, await sha2.sha256.digest(dagCBOR__namespace.encode(node)));
      chai_js.expect(cid$1.equals(cidCbor)).to.be.true();
    });
    it('should get a dag-cbor node local value', async () => {
      const result = await ipfs.dag.get(cidCbor, { path: 'someData' });
      chai_js.expect(result.value).to.eql('I am inside a Cbor object');
    });
    it.skip('should get dag-cbor node value one level deep', done => {
    });
    it.skip('should get dag-cbor node value two levels deep', done => {
    });
    it.skip('should get dag-cbor value via dag-pb node', done => {
    });
    it('should get only a CID, due to resolving locally only', async function () {
      const result = await ipfs.dag.get(cidCbor, {
        path: 'pb/Data',
        localResolve: true
      });
      chai_js.expect(result.value.equals(cidPb)).to.be.true();
    });
    it('should get dag-pb value via dag-cbor node', async function () {
      const result = await ipfs.dag.get(cidCbor, { path: 'pb/Data' });
      chai_js.expect(result.value).to.eql(fromString.fromString('I am inside a Protobuf'));
    });
    it('should get by CID with path option', async function () {
      const result = await ipfs.dag.get(cidCbor, { path: '/pb/Data' });
      chai_js.expect(result.value).to.eql(fromString.fromString('I am inside a Protobuf'));
    });
    it('should get only a CID, due to resolving locally only', async function () {
      const result = await ipfs.dag.get(cidCbor, {
        path: 'pb/Data',
        localResolve: true
      });
      chai_js.expect(result.value.equals(cidPb)).to.be.true();
    });
    it('should get with options and no path', async function () {
      const result = await ipfs.dag.get(cidCbor, { localResolve: true });
      chai_js.expect(result.value).to.deep.equal(nodeCbor);
    });
    it('should get a node added as CIDv0 with a CIDv1', async () => {
      const input = fromString.fromString(`TEST${ Math.random() }`);
      const node = {
        Data: input,
        Links: []
      };
      const cid = await ipfs.dag.put(node, {
        storeCodec: 'dag-pb',
        hashAlg: 'sha2-256',
        version: 0
      });
      chai_js.expect(cid.version).to.equal(0);
      const cidv1 = cid.toV1();
      const output = await ipfs.dag.get(cidv1);
      chai_js.expect(output.value.Data).to.eql(input);
    });
    it('should get a node added as CIDv1 with a CIDv0', async () => {
      const input = fromString.fromString(`TEST${ Math.random() }`);
      const res = await all__default["default"](ipfsUnixfsImporter.importer([{ content: input }], blockstoreAdapter(ipfs), {
        cidVersion: 1,
        rawLeaves: false
      }));
      const cidv1 = res[0].cid;
      chai_js.expect(cidv1.version).to.equal(1);
      const cidv0 = cidv1.toV0();
      const output = await ipfs.dag.get(cidv0);
      chai_js.expect(ipfsUnixfs.UnixFS.unmarshal(output.value.Data).data).to.eql(input);
    });
    it('should be able to get part of a dag-cbor node', async () => {
      const cbor = { foo: 'dag-cbor-bar' };
      const cid = await ipfs.dag.put(cbor, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      chai_js.expect(cid.code).to.equal(dagCBOR__namespace.code);
      chai_js.expect(cid.toString(base32.base32)).to.equal('bafyreic6f672hnponukaacmk2mmt7vs324zkagvu4hcww6yba6kby25zce');
      const result = await ipfs.dag.get(cid, { path: 'foo' });
      chai_js.expect(result.value).to.equal('dag-cbor-bar');
    });
    it('should be able to traverse from one dag-cbor node to another', async () => {
      const cbor1 = { foo: 'dag-cbor-bar' };
      const cid1 = await ipfs.dag.put(cbor1, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      const cbor2 = { other: cid1 };
      const cid2 = await ipfs.dag.put(cbor2, {
        storeCodec: 'dag-cbor',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.get(cid2, { path: 'other/foo' });
      chai_js.expect(result.value).to.equal('dag-cbor-bar');
    });
    it('should be able to get a DAG node with format raw', async () => {
      const buf = Uint8Array.from([
        0,
        1,
        2,
        3
      ]);
      const cid = await ipfs.dag.put(buf, {
        storeCodec: 'raw',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.get(cid);
      chai_js.expect(result.value).to.deep.equal(buf);
    });
    it('should be able to get a dag-cbor node with the identity hash', async () => {
      const identityData = fromString.fromString('A16461736466190144', 'base16upper');
      const identityHash = await identity.identity.digest(identityData);
      const identityCID = cid.CID.createV1(identity.identity.code, identityHash);
      const result = await ipfs.dag.get(identityCID);
      chai_js.expect(result.value).to.deep.equal(identityData);
    });
    it('should throw error for invalid string CID input', () => {
      return chai_js.expect(ipfs.dag.get('INVALID CID')).to.eventually.be.rejected();
    });
    it('should throw error for invalid buffer CID input', () => {
      return chai_js.expect(ipfs.dag.get(fromString.fromString('INVALID CID'))).to.eventually.be.rejected();
    });
    it('should return nested content when getting a CID with a path', async () => {
      const regularContent = { test: '123' };
      const cid1 = await ipfs.dag.put(regularContent);
      const linkedContent = { link: cid1 };
      const cid2 = await ipfs.dag.put(linkedContent);
      const atPath = await ipfs.dag.get(cid2, { path: '/link' });
      chai_js.expect(atPath).to.have.deep.property('value', regularContent);
    });
    it('should not return nested content when getting a CID with a path and localResolve is true', async () => {
      const regularContent = { test: '123' };
      const cid1 = await ipfs.dag.put(regularContent);
      const linkedContent = { link: cid1 };
      const cid2 = await ipfs.dag.put(linkedContent);
      const atPath = await ipfs.dag.get(cid2, {
        path: '/link',
        localResolve: true
      });
      chai_js.expect(atPath).to.have.deep.property('value').that.is.an.instanceOf(cid.CID);
    });
    it('should get a dag-jose node', async () => {
      const cid = await ipfs.dag.put(joseNode, {
        storeCodec: 'dag-jose',
        hashAlg: 'sha2-256'
      });
      const result = await ipfs.dag.get(cid);
      const node = result.value;
      chai_js.expect(joseNode).to.eql(node);
    });
    it('should get a dag-jose node with path', async () => {
      const result = await ipfs.dag.get(cidJose, { path: '/' });
      const node = result.value;
      const cid$1 = cid.CID.createV1(dagJOSE__namespace.code, await sha2.sha256.digest(dagJOSE__namespace.encode(node)));
      chai_js.expect(cid$1.equals(cidJose)).to.be.true();
    });
    it('should get a dag-jose node local value', async () => {
      const result = await ipfs.dag.get(cidJose, { path: 'payload' });
      const converted = dagJOSE__namespace.toGeneral(nodeJose);
      chai_js.expect(result.value).to.eql('payload' in converted && converted.payload);
    });
    it('should get dag-cbor value via dag-jose node', async function () {
      const result = await ipfs.dag.get(cidJose, { path: 'link/someData' });
      chai_js.expect(result.value).to.eql('I am inside a Cbor object');
    });
    it('should get dag-cbor cid via dag-jose node if local resolve', async function () {
      const result = await ipfs.dag.get(cidJose, {
        path: 'link',
        localResolve: true
      });
      chai_js.expect(result.value).to.eql(cidCbor);
    });
  });
}

exports.testGet = testGet;
