const {
  createDefaultEnvironment,
  destroyDefaultEnvironment
} = require('@cardstack/test-support/env');
const JSONAPIFactory = require('@cardstack/test-support/jsonapi-factory');
const { join } = require('path');
const { readFileSync, readdirSync } = require('fs');
const { promisify } = require('util');
const sinon = require('sinon');
const temp = require('temp').track();
const service = require('../service');

const mkdir = promisify(temp.mkdir);

const privateKey = readFileSync(join(__dirname, 'git-ssh-server', 'cardstack-test-key'), 'utf8');

describe('local git cache service', function() {
  this.timeout(10000);

  beforeEach(() => {
    service.clearCache();
  });

  afterEach(() => {
    service.clearCache();
  });

  it('creates a local clone of the repo with a naming convention', async function() {
    let tempRepoPath = await mkdir('test-1');

    let factory = new JSONAPIFactory();

    let dataSource1 = factory.addResource('data-sources')
        .withAttributes({
          'source-type': '@cardstack/git',
          params: {
            remote: {
              url: 'ssh://root@localhost:9022/root/data-test',
              privateKey,
              cacheDir: tempRepoPath,
            }
          }
        });

    factory.addResource('plugin-configs', '@cardstack/hub')
      .withRelated(
        'default-data-source-test-1',
        dataSource1
      );

    let env = await createDefaultEnvironment(`${__dirname}/..`, factory.getModels());

    expect(readdirSync(tempRepoPath)).to.have.length(1);

    await temp.cleanup();
    await destroyDefaultEnvironment(env);
  });

  it('consideres localhost and 127.0.0.1 different for the purposes of a local cache', async function() {
    let tempRepoPath = await mkdir('test-2');

    let factory = new JSONAPIFactory();

    let dataSource1 = factory.addResource('data-sources')
        .withAttributes({
          'source-type': '@cardstack/git',
          params: {
            remote: {
              url: 'ssh://root@localhost:9022/root/data-test',
              privateKey,
              cacheDir: tempRepoPath,
            }
          }
        });

    let dataSource2 = factory.addResource('data-sources')
        .withAttributes({
          'source-type': '@cardstack/git',
          params: {
            remote: {
              url: 'ssh://root@127.0.0.1:9022/root/data-test',
              privateKey,
              cacheDir: tempRepoPath,
            }
          }
        });

    factory.addResource('plugin-configs', '@cardstack/hub')
      .withRelated(
        'default-data-source',
        dataSource1
      );

    factory.addResource('plugin-configs', '@cardstack/hub')
      .withRelated(
        'second-data-source',
        dataSource2
      );

    let env = await createDefaultEnvironment(`${__dirname}/..`, factory.getModels());

    expect(readdirSync(tempRepoPath)).to.have.length(2);

    await temp.cleanup();
    await destroyDefaultEnvironment(env);
  });

  it('only creates one local repo if the remote is the same for the writer and indexer', async function() {
    sinon.spy(service, 'getRepo');
    sinon.spy(service, '_makeRepo');

    let tempRepoPath = await mkdir('test-3');

    let factory = new JSONAPIFactory();

    let dataSource1 = factory.addResource('data-sources')
        .withAttributes({
          'source-type': '@cardstack/git',
          params: {
            remote: {
              url: 'ssh://root@localhost:9022/root/data-test',
              privateKey,
              cacheDir: tempRepoPath,
            }
          }
        });

    factory.addResource('plugin-configs', '@cardstack/hub')
      .withRelated(
        'default-data-source-test-1',
        dataSource1
      );

    let env = await createDefaultEnvironment(`${__dirname}/..`, factory.getModels());

    sinon.assert.calledTwice(service.getRepo);
    sinon.assert.calledOnce(service._makeRepo);

    await temp.cleanup();
    await destroyDefaultEnvironment(env);
    service.getRepo.restore();
    service._makeRepo.restore();
  });
});

@@ -243,16 +243,38 @@
 ddirSync
+, mkdirSync, rmdirSync
  %7D = req
@@ -4065,13 +4065,1438 @@
 );%0A  %7D);
+%0A%0A  it('allows you to restart the hub and it will re-use the exising cached folder', async function() %7B%0A    this.timeout(20000);%0A%0A    sinon.spy(service, 'getRepo');%0A    sinon.spy(service, '_makeRepo');%0A%0A    let tempRepoPath = await temp.path('test-4');%0A    mkdirSync(tempRepoPath);%0A%0A    let factory = new JSONAPIFactory();%0A%0A    let dataSource1 = factory.addResource('data-sources')%0A        .withAttributes(%7B%0A          'source-type': '@cardstack/git',%0A          params: %7B%0A            remote: %7B%0A              url: 'ssh://root@localhost:9022/root/data-test',%0A              privateKey,%0A              cacheDir: tempRepoPath,%0A            %7D%0A          %7D%0A        %7D);%0A%0A    factory.addResource('plugin-configs', '@cardstack/hub')%0A      .withRelated(%0A        'default-data-source-test-1',%0A        dataSource1%0A      );%0A%0A    let env = await createDefaultEnvironment(%60$%7B__dirname%7D/..%60, factory.getModels());%0A%0A    sinon.assert.calledTwice(service.getRepo);%0A    sinon.assert.calledOnce(service._makeRepo);%0A%0A    await destroyDefaultEnvironment(env);%0A    service.clearCache();%0A%0A    // create the environment a second time%0A    env = await createDefaultEnvironment(%60$%7B__dirname%7D/..%60, factory.getModels());%0A%0A    sinon.assert.callCount(service.getRepo, 4);%0A    sinon.assert.calledTwice(service._makeRepo);%0A%0A%0A    rmdirSync(tempRepoPath);%0A    service.getRepo.restore();%0A    service._makeRepo.restore();%0A    await destroyDefaultEnvironment(env);%0A  %7D);
 %0A%7D);%0A

add failing test for cloned repo reuse case