
const fs = require('fs');
const path = require('path');
const findParent = require('./utils/find-parent');
const findHooksDir = require('./utils/find-hooks-dir');
const getHookScript = require('./utils/get-hook-script');
const is = require('./utils/is');
const hooks = require('./hooks.json');

const SKIP = 'SKIP';
const UPDATE = 'UPDATE';
const MIGRATE_GHOOKS = 'MIGRATE_GHOOKS';
const MIGRATE_PRE_COMMIT = 'MIGRATE_PRE_COMMIT';
const CREATE = 'CREATE';

function write(filename, data) {
  fs.writeFileSync(filename, data);
  fs.chmodSync(filename, parseInt('0755', 8));
}

function createHook(depDir, projectDir, hooksDir, hookName, runnerPath) {
  const filename = path.join(hooksDir, hookName);

  let packageDir;
  // prioritize package.json next to .git
  // this avoids double-install in lerna monorepos where both root and sub
  // package depends on this module
  if (fs.existsSync(path.join(projectDir, 'package.json'))) {
    packageDir = projectDir;
  } else {
    packageDir = findParent(depDir, 'package.json');
  }

  // In order to support projects with package.json in a different directory
  // than .git, find relative path from project directory to package.json
  const relativePath = path.join('.', path.relative(projectDir, packageDir));

  const hookScript = getHookScript(hookName, relativePath, runnerPath);

  // Create hooks directory if needed
  if (!fs.existsSync(hooksDir)) fs.mkdirSync(hooksDir);

  if (!fs.existsSync(filename)) {
    write(filename, hookScript);
    return CREATE;
  }

  if (is.ghooks(filename)) {
    write(filename, hookScript);
    return MIGRATE_GHOOKS;
  }

  if (is.preCommit(filename)) {
    write(filename, hookScript);
    return MIGRATE_PRE_COMMIT;
  }

  if (is.huskyOrYorkie(filename)) {
    write(filename, hookScript);
    return UPDATE;
  }

  return SKIP;
}

function installFrom(depDir) {
  try {
    const isInSubNodeModule = (depDir.match(/node_modules/g) || []).length > 1;
    if (isInSubNodeModule) {
      return console.log(
        "trying to install from sub 'node_module' directory,",
        'skipping Git hooks installation'
      );
    }

    const projectDir = findParent(depDir, 'package.json');
    const hooksDir = findHooksDir(projectDir);
    const runnerPath = './node_modules/@ne_fe/boot/yorkie/src/runner.js';

    if (hooksDir) {
      hooks
        .map(function(hookName) {
          return {
            hookName,
            action: createHook(depDir, projectDir, hooksDir, hookName, runnerPath),
          };
        })
        .forEach(function(item) {
          switch (item.action) {
            case MIGRATE_GHOOKS:
              console.log(`migrating existing ghooks ${item.hookName} script`);
              break;
            case MIGRATE_PRE_COMMIT:
              console.log(
                `migrating existing pre-commit ${item.hookName} script`
              );
              break;
            case UPDATE:
              break;
            case SKIP:
              console.log(`skipping ${item.hookName} hook (existing user hook)`);
              break;
            case CREATE:
              break;
            default:
              console.error('Unknown action');
          }
        });
      console.log('done\n');
    } else {
      console.log("can't find .git directory, skipping Git hooks installation");
    }
  } catch (e) {
    console.error(e);
  }
}

module.exports = installFrom;
