'use strict';

const FS = require('../models/FS');
const User = require('../models/User');
const Org = require('../models/Org');
const API = require('../models/API');
const Service = require('../models/Service');
const Instance = require('../models/Instance');
const Code = require('../models/Code');

module.exports = async (config, cli) => {
  cli.logLogo();
  cli.sessionStart('copying', { timer: true });

  const fs = new FS();
  const user = new User();
  const api = new API();

  const sourceInstanceName = config.source || config.s || user.username;
  const destinationInstanceName = config.target || config.t || user.username;
  const copyData = config.data;
  const overwriteCwd = config.overwrite;

  if (!(await fs.isCwdEmpty()) && !overwriteCwd) {
    throw new Error('your cwd is not empty. To overwrite the cwd, pass the --overwrite flag.');
  }

  // todo users need to specify an org name when copy
  const org = new Org({ user });
  await org.authorize();

  if (!org.accessKey) {
    // not logged in
    throw new Error('please login by running "sc login".');
  }

  if (!org.orgName) {
    // this could happen if using access key env var
    // without setting org in package.json
    throw new Error('please add an "org" property in package.json');
  }

  api.authorize(org);

  const service = new Service({ api, org });

  let isFirstLog = true;
  if (sourceInstanceName !== destinationInstanceName) {
    await service.copy({
      sourceInstanceName,
      destinationInstanceName,
      copyData,
    });
    if (isFirstLog) {
      cli.log();
      isFirstLog = false;
    }
    cli.logSuccess(
      `copied instance ${cli.styles.bold(sourceInstanceName)} code to instance ${cli.styles.bold(
        destinationInstanceName
      )}`
    );
    if (copyData) {
      cli.logSuccess(
        `copied instance ${cli.styles.bold(sourceInstanceName)} data to instance ${cli.styles.bold(
          destinationInstanceName
        )}`
      );
    }
  }

  const instance = new Instance({
    fs,
    api,
    org,
    service,
    instanceName: destinationInstanceName,
  });

  const code = new Code({
    fs,
    api,
    org,
    service,
    instance,
  });

  await code.getUrls();

  if (overwriteCwd) {
    await fs.emptyDir();
  }

  await code.downloadSource();

  if (isFirstLog) {
    cli.log();
    isFirstLog = false;
  }
  cli.logSuccess(`downloaded instance ${cli.styles.bold(destinationInstanceName)} into the cwd`);

  cli.log();
  cli.logUrl(instance.url);

  cli.sessionStop('copied', 'success');
};
