/**
 * Created by geweimin on 17/7/17.
 */
const chalk = require('chalk');
const copyAndReplace = require('../util/copyAndReplace');
const path = require('path');
const prompt = require('./promptSync')();
const walk = require('../util/walk');


function copyProjectTemplateAndReplace(srcPath, destPath, newProjectName, options) {
  if (!srcPath) { throw new Error('Need a path to copy from'); }
  if (!destPath) { throw new Error('Need a path to copy to'); }
  if (!newProjectName) { throw new Error('Need a project name'); }

  options = options || {};

  walk(srcPath).forEach(absoluteSrcFilePath => {
    
    const relativeFilePath = path.relative(srcPath, absoluteSrcFilePath);
    const relativeRenamedPath = dotFilePath(relativeFilePath)
      .replace(/HelloWorld/g, newProjectName)
      .replace(/helloworld/g, newProjectName.toLowerCase());

    // Templates may contain files that we don't want to copy.
    // Examples:
    // - Dummy package.json file included in the template only for publishing to npm
    // - Docs specific to the template (.md files)
    if (options.ignorePaths) {
      if (!Array.isArray(options.ignorePaths)) {
        throw new Error('options.ignorePaths must be an array');
      }
      if (options.ignorePaths.some(ignorePath => ignorePath === relativeFilePath)) {
        // Skip copying this file
        return;
      }
    }

    let contentChangedCallback = null;
    if (options.upgrade && (!options.force)) {
      contentChangedCallback = (_, contentChanged) => {
        return upgradeFileContentChangedCallback(absoluteSrcFilePath,
          relativeRenamedPath,
          contentChanged
        );
      };
    }
    copyAndReplace(
      absoluteSrcFilePath,
      path.resolve(destPath, relativeRenamedPath),
      {
        'Hello App Display Name': options.displayName || newProjectName,
        'HelloWorld': newProjectName,
        'helloworld': newProjectName.toLowerCase(),
      },
      contentChangedCallback
    );
  });
}

function dotFilePath(path) {
  if (!path) return path;
  return path
    .replace('_gitignore', '.gitignore')
    .replace('_gitattributes', '.gitattributes')
    .replace('_babelrc', '.babelrc')
    .replace('_flowconfig', '.flowconfig')
    .replace('_buckconfig', '.buckconfig')
    .replace('_watchmanconfig', '.watchmanconfig');
}

function upgradeFileContentChangedCallback(
  absoluteSrcFilePath,
  relativeDestPath,
  contentChanged
) {
  if (contentChanged === 'new') {
    console.log(chalk.bold('new') + ' ' + relativeDestPath);
    return 'overwrite';
  } else if (contentChanged === 'changed') {
    console.log(chalk.bold(relativeDestPath) + ' ' +
      'has changed in the new version.\nDo you want to keep your ' +
      relativeDestPath + ' or replace it with the ' +
      'latest version?\nIf you ever made any changes ' +
      'to this file, you\'ll probably want to keep it.\n' +
      'You can see the new version here: ' + absoluteSrcFilePath + '\n' +
      'Do you want to replace ' + relativeDestPath + '? ' +
      'Answer y to replace, n to keep your version: ');
    const answer = prompt();
    if (answer === 'y') {
      console.log('Replacing ' + relativeDestPath);
      return 'overwrite';
    } else {
      console.log('Keeping your ' + relativeDestPath);
      return 'keep';
    }
  } else if (contentChanged === 'identical') {
    return 'keep';
  } else {
    throw new Error(`Unkown file changed state: ${relativeDestPath}, ${contentChanged}`);
  }
}

module.exports = copyProjectTemplateAndReplace;
