'use strict';

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

var fromString = require('uint8arrays/from-string');
var toString = require('uint8arrays/to-string');
var concat = require('uint8arrays/concat');
var index = require('./utils/index.js');
var cid = require('multiformats/cid');
var all = require('it-all');
var drain = require('it-drain');
var last = require('it-last');
var map = require('it-map');
var chai_js = require('aegir/utils/chai.js');
var mocha = require('./utils/mocha.js');
var testTimeout = require('./utils/test-timeout.js');
var ipfsUnixfsImporter = require('ipfs-unixfs-importer');
var blockstoreAdapter = require('./utils/blockstore-adapter.js');
var itTar = require('it-tar');
var itPipe = require('it-pipe');
var toBuffer = require('it-to-buffer');
var Pako = require('pako');

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

var all__default = /*#__PURE__*/_interopDefaultLegacy(all);
var drain__default = /*#__PURE__*/_interopDefaultLegacy(drain);
var last__default = /*#__PURE__*/_interopDefaultLegacy(last);
var map__default = /*#__PURE__*/_interopDefaultLegacy(map);
var toBuffer__default = /*#__PURE__*/_interopDefaultLegacy(toBuffer);
var Pako__default = /*#__PURE__*/_interopDefaultLegacy(Pako);

const content = (name, path) => {
  if (!path) {
    path = name;
  }
  return {
    path: `test-folder/${ path }`,
    content: index.fixtures.directory.files[name]
  };
};
const emptyDir = name => ({ path: `test-folder/${ name }` });
function testGet(factory, options) {
  const describe = mocha.getDescribe(options);
  const it = mocha.getIt(options);
  describe('.get', function () {
    this.timeout(120 * 1000);
    let ipfs;
    async function* gzipped(source) {
      const inflator = new Pako__default["default"].Inflate();
      for await (const buf of source) {
        inflator.push(buf, false);
      }
      inflator.push(new Uint8Array(0), true);
      if (inflator.err) {
        throw new Error(`Error ungzipping - message: "${ inflator.msg }" code: ${ inflator.err }`);
      }
      if (inflator.result instanceof Uint8Array) {
        yield inflator.result;
      } else {
        throw new Error('Unexpected gzip data type');
      }
    }
    async function* tarballed(source) {
      yield* itPipe.pipe(source, itTar.extract(), async function* (source) {
        for await (const entry of source) {
          yield {
            ...entry,
            body: await toBuffer__default["default"](map__default["default"](entry.body, buf => buf.slice()))
          };
        }
      });
    }
    async function collect(source) {
      return all__default["default"](source);
    }
    before(async () => {
      ipfs = (await factory.spawn()).api;
      await Promise.all([
        all__default["default"](ipfsUnixfsImporter.importer({ content: index.fixtures.smallFile.data }, blockstoreAdapter(ipfs))),
        all__default["default"](ipfsUnixfsImporter.importer({ content: index.fixtures.bigFile.data }, blockstoreAdapter(ipfs)))
      ]);
    });
    after(() => factory.clean());
    it('should respect timeout option when getting files', () => {
      return testTimeout(() => drain__default["default"](ipfs.get(cid.CID.parse('QmPDqvcuA4AkhBLBuh2y49yhUB98rCnxPxa3eVNC1kAbS1'), { timeout: 1 })));
    });
    it('should get with a base58 encoded multihash', async () => {
      const output = await itPipe.pipe(ipfs.get(index.fixtures.smallFile.cid), tarballed, collect);
      chai_js.expect(output).to.have.lengthOf(1);
      chai_js.expect(output).to.have.nested.property('[0].header.name', index.fixtures.smallFile.cid.toString());
      chai_js.expect(output).to.have.nested.property('[0].body').that.equalBytes(index.fixtures.smallFile.data);
    });
    it('should get a file added as CIDv0 with a CIDv1', async () => {
      const input = fromString.fromString(`TEST${ Math.random() }`);
      const res = await all__default["default"](ipfsUnixfsImporter.importer({ content: input }, blockstoreAdapter(ipfs)));
      const cidv0 = res[0].cid;
      chai_js.expect(cidv0.version).to.equal(0);
      const cidv1 = cidv0.toV1();
      const output = await itPipe.pipe(ipfs.get(cidv1), tarballed, collect);
      chai_js.expect(output).to.have.lengthOf(1);
      chai_js.expect(output).to.have.nested.property('[0].header.name', cidv1.toString());
      chai_js.expect(output).to.have.nested.property('[0].body').that.equalBytes(input);
    });
    it('should get a file 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 itPipe.pipe(ipfs.get(cidv0), tarballed, collect);
      chai_js.expect(output).to.have.lengthOf(1);
      chai_js.expect(output).to.have.nested.property('[0].header.name', cidv0.toString());
      chai_js.expect(output).to.have.nested.property('[0].body').that.equalBytes(input);
    });
    it('should get a file added as CIDv1 with rawLeaves', async () => {
      const input = fromString.fromString(`TEST${ Math.random() }`);
      const res = await all__default["default"](ipfsUnixfsImporter.importer({ content: input }, blockstoreAdapter(ipfs), {
        cidVersion: 1,
        rawLeaves: true
      }));
      const cidv1 = res[0].cid;
      chai_js.expect(cidv1.version).to.equal(1);
      const output = await itPipe.pipe(ipfs.get(cidv1), tarballed, collect);
      chai_js.expect(output).to.have.lengthOf(1);
      chai_js.expect(output).to.have.nested.property('[0].header.name', cidv1.toString());
      chai_js.expect(output).to.have.nested.property('[0].body').that.equalBytes(input);
    });
    it('should get a BIG file', async () => {
      const output = await itPipe.pipe(ipfs.get(index.fixtures.bigFile.cid), tarballed, collect);
      chai_js.expect(output).to.have.lengthOf(1);
      chai_js.expect(output).to.have.nested.property('[0].header.name', index.fixtures.bigFile.cid.toString());
      chai_js.expect(output).to.have.nested.property('[0].body').that.equalBytes(index.fixtures.bigFile.data);
    });
    it('should get a directory', async function () {
      const dirs = [
        content('pp.txt'),
        content('holmes.txt'),
        content('jungle.txt'),
        content('alice.txt'),
        emptyDir('empty-folder'),
        content('files/hello.txt'),
        content('files/ipfs.txt'),
        emptyDir('files/empty')
      ];
      const res = await all__default["default"](ipfsUnixfsImporter.importer(dirs, blockstoreAdapter(ipfs)));
      const {cid} = res[res.length - 1];
      chai_js.expect(`${ cid }`).to.equal(index.fixtures.directory.cid.toString());
      const output = await itPipe.pipe(ipfs.get(cid), tarballed, collect);
      const paths = output.map(file => {
        return file.header.name;
      });
      chai_js.expect(paths).to.include.members([
        'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP',
        'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/alice.txt',
        'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/empty-folder',
        'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/files',
        'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/files/empty',
        'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/files/hello.txt',
        'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/files/ipfs.txt',
        'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/holmes.txt',
        'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/jungle.txt',
        'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/pp.txt'
      ]);
      chai_js.expect(output.map(f => toString.toString(f.body))).to.include.members([
        index.fixtures.directory.files['alice.txt'].toString(),
        index.fixtures.directory.files['files/hello.txt'].toString(),
        index.fixtures.directory.files['files/ipfs.txt'].toString(),
        index.fixtures.directory.files['holmes.txt'].toString(),
        index.fixtures.directory.files['jungle.txt'].toString(),
        index.fixtures.directory.files['pp.txt'].toString()
      ]);
    });
    it('should get a nested directory', async function () {
      const dirs = [
        content('pp.txt', 'pp.txt'),
        content('holmes.txt', 'foo/holmes.txt'),
        content('jungle.txt', 'foo/bar/jungle.txt')
      ];
      const res = await all__default["default"](ipfsUnixfsImporter.importer(dirs, blockstoreAdapter(ipfs)));
      const {cid} = res[res.length - 1];
      chai_js.expect(`${ cid }`).to.equal('QmVMXXo3c2bDPH9ayy2VKoXpykfYJHwAcU5YCJjPf7jg3g');
      const output = await itPipe.pipe(ipfs.get(cid), tarballed, collect);
      chai_js.expect(output.map(file => {
        return file.header.name;
      })).to.include.members([
        'QmVMXXo3c2bDPH9ayy2VKoXpykfYJHwAcU5YCJjPf7jg3g',
        'QmVMXXo3c2bDPH9ayy2VKoXpykfYJHwAcU5YCJjPf7jg3g/pp.txt',
        'QmVMXXo3c2bDPH9ayy2VKoXpykfYJHwAcU5YCJjPf7jg3g/foo/holmes.txt',
        'QmVMXXo3c2bDPH9ayy2VKoXpykfYJHwAcU5YCJjPf7jg3g/foo/bar/jungle.txt'
      ]);
      chai_js.expect(output.map(f => toString.toString(f.body))).to.include.members([
        index.fixtures.directory.files['pp.txt'].toString(),
        index.fixtures.directory.files['holmes.txt'].toString(),
        index.fixtures.directory.files['jungle.txt'].toString()
      ]);
    });
    it('should get with ipfs path, as object and nested value', async () => {
      const file = {
        path: 'a/testfile.txt',
        content: index.fixtures.smallFile.data
      };
      const fileAdded = await last__default["default"](ipfsUnixfsImporter.importer([file], blockstoreAdapter(ipfs)));
      if (!fileAdded) {
        throw new Error('No file was added');
      }
      chai_js.expect(fileAdded).to.have.property('path', 'a');
      const output = await itPipe.pipe(ipfs.get(`/ipfs/${ fileAdded.cid }/testfile.txt`), tarballed, collect);
      chai_js.expect(output).to.be.length(1);
      chai_js.expect(toString.toString(output[0].body)).to.equal('Plz add me!\n');
    });
    it('should compress a file directly', async () => {
      const output = await itPipe.pipe(ipfs.get(index.fixtures.smallFile.cid, {
        compress: true,
        compressionLevel: 5
      }), gzipped, collect);
      chai_js.expect(concat.concat(output)).to.equalBytes(index.fixtures.smallFile.data);
    });
    it('should compress a file as a tarball', async () => {
      const output = await itPipe.pipe(ipfs.get(index.fixtures.smallFile.cid, {
        archive: true,
        compress: true,
        compressionLevel: 5
      }), gzipped, tarballed, collect);
      chai_js.expect(output).to.have.nested.property('[0].body').that.equalBytes(index.fixtures.smallFile.data);
    });
    it('should not compress a directory', async () => {
      const dirs = [
        content('pp.txt'),
        emptyDir('empty-folder'),
        content('files/hello.txt')
      ];
      const res = await all__default["default"](ipfsUnixfsImporter.importer(dirs, blockstoreAdapter(ipfs)));
      const {cid} = res[res.length - 1];
      await chai_js.expect(drain__default["default"](ipfs.get(cid, {
        compress: true,
        compressionLevel: 5
      }))).to.eventually.be.rejectedWith(/file is not regular/);
    });
    it('should compress a file with invalid compression level', async () => {
      await chai_js.expect(drain__default["default"](ipfs.get(index.fixtures.smallFile.cid, {
        compress: true,
        compressionLevel: 10
      }))).to.eventually.be.rejected();
    });
    it('should compress a directory as a tarball', async () => {
      const dirs = [
        content('pp.txt'),
        emptyDir('empty-folder'),
        content('files/hello.txt')
      ];
      const res = await all__default["default"](ipfsUnixfsImporter.importer(dirs, blockstoreAdapter(ipfs)));
      const {cid} = res[res.length - 1];
      const output = await itPipe.pipe(ipfs.get(cid, {
        archive: true,
        compress: true,
        compressionLevel: 5
      }), gzipped, tarballed, collect);
      const paths = output.map(file => {
        return file.header.name;
      });
      chai_js.expect(paths).to.include.members([
        'QmXpbhYKheGs5sopefFjsABsjr363QkRaJT4miRsN88ABU',
        'QmXpbhYKheGs5sopefFjsABsjr363QkRaJT4miRsN88ABU/empty-folder',
        'QmXpbhYKheGs5sopefFjsABsjr363QkRaJT4miRsN88ABU/files/hello.txt',
        'QmXpbhYKheGs5sopefFjsABsjr363QkRaJT4miRsN88ABU/pp.txt'
      ]);
      chai_js.expect(output.map(f => toString.toString(f.body))).to.include.members([
        index.fixtures.directory.files['files/hello.txt'].toString(),
        index.fixtures.directory.files['pp.txt'].toString()
      ]);
    });
    it('should error on invalid key', async () => {
      const invalidCid = 'somethingNotMultihash';
      await chai_js.expect(all__default["default"](ipfs.get(invalidCid))).to.eventually.be.rejected();
    });
    it('get path containing "+"s', async () => {
      const filename = 'ti,c64x+mega++mod-pic.txt';
      const subdir = 'tmp/c++files';
      const expectedCid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff';
      const path = `${ subdir }/${ filename }`;
      const files = await all__default["default"](ipfs.addAll([{
          path,
          content: path
        }]));
      chai_js.expect(files[2].cid.toString()).to.equal(expectedCid);
      const cid$1 = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff';
      const output = await itPipe.pipe(ipfs.get(cid.CID.parse(cid$1)), tarballed, collect);
      chai_js.expect(output).to.be.an('array').with.lengthOf(3);
      chai_js.expect(output).to.have.nested.property('[0].header.name', cid$1);
      chai_js.expect(output).to.have.nested.property('[1].header.name', `${ cid$1 }/c++files`);
      chai_js.expect(output).to.have.nested.property('[2].header.name', `${ cid$1 }/c++files/ti,c64x+mega++mod-pic.txt`);
    });
  });
}

exports.testGet = testGet;
