'use strict';

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

var fromString = require('uint8arrays/from-string');
var chai_js = require('aegir/utils/chai.js');
var mocha = require('../utils/mocha.js');
var cid = require('multiformats/cid');
var createShardedDirectory = require('../utils/create-sharded-directory.js');
var all = require('it-all');
var isoRandomStream = require('iso-random-stream');
var raw = require('multiformats/codecs/raw');

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 all__default = /*#__PURE__*/_interopDefaultLegacy(all);
var raw__namespace = /*#__PURE__*/_interopNamespace(raw);

function testLs(factory, options) {
  const describe = mocha.getDescribe(options);
  const it = mocha.getIt(options);
  const largeFile = isoRandomStream.randomBytes(490668);
  describe('.files.ls', function () {
    this.timeout(120 * 1000);
    let ipfs;
    before(async () => {
      ipfs = (await factory.spawn()).api;
    });
    after(() => factory.clean());
    it('should require a path', () => {
      chai_js.expect(all__default["default"](ipfs.files.ls())).to.eventually.be.rejected();
    });
    it('lists the root directory', async () => {
      const fileName = `small-file-${ Math.random() }.txt`;
      const content = fromString.fromString('Hello world');
      await ipfs.files.write(`/${ fileName }`, content, { create: true });
      const files = await all__default["default"](ipfs.files.ls('/'));
      chai_js.expect(files).to.have.lengthOf(1).and.to.containSubset([{
          cid: cid.CID.parse('Qmetpc7cZmN25Wcc6R27cGCAvCDqCS5GjHG4v7xABEfpmJ'),
          name: fileName,
          size: content.length,
          type: 'file'
        }]);
    });
    it('refuses to lists files with an empty path', async () => {
      await chai_js.expect(all__default["default"](ipfs.files.ls(''))).to.eventually.be.rejected();
    });
    it('refuses to lists files with an invalid path', async () => {
      await chai_js.expect(all__default["default"](ipfs.files.ls('not-valid'))).to.eventually.be.rejected();
    });
    it('lists files in a directory', async () => {
      const dirName = `dir-${ Math.random() }`;
      const fileName = `small-file-${ Math.random() }.txt`;
      const content = fromString.fromString('Hello world');
      await ipfs.files.write(`/${ dirName }/${ fileName }`, content, {
        create: true,
        parents: true
      });
      const files = await all__default["default"](ipfs.files.ls(`/${ dirName }`));
      chai_js.expect(files).to.have.lengthOf(1).and.to.containSubset([{
          cid: cid.CID.parse('Qmetpc7cZmN25Wcc6R27cGCAvCDqCS5GjHG4v7xABEfpmJ'),
          name: fileName,
          size: content.length,
          type: 'file'
        }]);
    });
    it('lists a file', async () => {
      const fileName = `small-file-${ Math.random() }.txt`;
      const content = fromString.fromString('Hello world');
      await ipfs.files.write(`/${ fileName }`, content, { create: true });
      const files = await all__default["default"](ipfs.files.ls(`/${ fileName }`));
      chai_js.expect(files).to.have.lengthOf(1).and.to.containSubset([{
          cid: cid.CID.parse('Qmetpc7cZmN25Wcc6R27cGCAvCDqCS5GjHG4v7xABEfpmJ'),
          name: fileName,
          size: content.length,
          type: 'file'
        }]);
    });
    it('fails to list non-existent file', async () => {
      await chai_js.expect(all__default["default"](ipfs.files.ls('/i-do-not-exist'))).to.eventually.be.rejected();
    });
    it('lists a raw node', async () => {
      const filePath = '/stat/large-file.txt';
      await ipfs.files.write(filePath, largeFile, {
        create: true,
        parents: true,
        rawLeaves: true
      });
      const stats = await ipfs.files.stat(filePath);
      const {value: node} = await ipfs.dag.get(stats.cid);
      chai_js.expect(node).to.have.nested.property('Links[0].Hash.code', raw__namespace.code);
      const child = node.Links[0];
      const files = await all__default["default"](ipfs.files.ls(`/ipfs/${ child.Hash }`));
      chai_js.expect(files).to.have.lengthOf(1).and.to.containSubset([{
          cid: child.Hash,
          name: child.Hash.toString(),
          size: 262144,
          type: 'file'
        }]);
    });
    it('lists a raw node in an mfs directory', async () => {
      const filePath = '/stat/large-file.txt';
      await ipfs.files.write(filePath, largeFile, {
        create: true,
        parents: true,
        rawLeaves: true
      });
      const stats = await ipfs.files.stat(filePath);
      const cid = stats.cid;
      const {value: node} = await ipfs.dag.get(cid);
      chai_js.expect(node).to.have.nested.property('Links[0].Hash.code', raw__namespace.code);
      const child = node.Links[0];
      const dir = `/dir-with-raw-${ Math.random() }`;
      const path = `${ dir }/raw-${ Math.random() }`;
      await ipfs.files.mkdir(dir);
      await ipfs.files.cp(`/ipfs/${ child.Hash }`, path);
      const files = await all__default["default"](ipfs.files.ls(`/ipfs/${ child.Hash }`));
      chai_js.expect(files).to.have.lengthOf(1).and.to.containSubset([{
          cid: child.Hash,
          name: child.Hash.toString(),
          size: 262144,
          type: 'file'
        }]);
    });
    describe('with sharding', () => {
      let ipfs;
      before(async function () {
        const ipfsd = await factory.spawn({
          ipfsOptions: {
            EXPERIMENTAL: { sharding: true },
            config: { Internal: { UnixFSShardingSizeThreshold: '1B' } }
          }
        });
        ipfs = ipfsd.api;
      });
      it('lists a sharded directory contents', async () => {
        const fileCount = 1001;
        const dirPath = await createShardedDirectory.createShardedDirectory(ipfs, fileCount);
        const files = await all__default["default"](ipfs.files.ls(dirPath));
        chai_js.expect(files.length).to.equal(fileCount);
        files.forEach(file => {
          chai_js.expect(file.type).to.equal('file');
        });
      });
      it('lists a file inside a sharded directory directly', async () => {
        const dirPath = await createShardedDirectory.createShardedDirectory(ipfs);
        const files = await all__default["default"](ipfs.files.ls(dirPath));
        const filePath = `${ dirPath }/${ files[0].name }`;
        const file = await all__default["default"](ipfs.files.ls(filePath));
        chai_js.expect(file).to.have.lengthOf(1).and.to.containSubset([files[0]]);
      });
      it('lists the contents of a directory inside a sharded directory', async () => {
        const shardedDirPath = await createShardedDirectory.createShardedDirectory(ipfs);
        const dirPath = `${ shardedDirPath }/subdir-${ Math.random() }`;
        const fileName = `small-file-${ Math.random() }.txt`;
        await ipfs.files.mkdir(`${ dirPath }`);
        await ipfs.files.write(`${ dirPath }/${ fileName }`, Uint8Array.from([
          0,
          1,
          2,
          3
        ]), { create: true });
        const files = await all__default["default"](ipfs.files.ls(dirPath));
        chai_js.expect(files.length).to.equal(1);
        chai_js.expect(files.filter(file => file.name === fileName)).to.be.ok();
      });
    });
  });
}

exports.testLs = testLs;
