'use strict';

// GLOBAL
const path = require('path');
const fs = require('fs');

// LOCAL
const gitUtils = require('./git-utils');
const tools = require('./tools');
const configUtils = require('../csdr/config/config-utils');

const DEFAULT_TYPE = 'other';
const DEFAULT_CATEGORY = 'other';

const TYPES = {
  build: 'Build System / Dependencies',
  ci: 'Continuous Integration',
  chore: 'Chores',
  docs: 'Documentation Changes',
  feat: 'New Features',
  fix: 'Bug Fixes',
  other: 'Other Changes',
  perf: 'Performance Improvements',
  refactor: 'Refactors',
  revert: 'Reverts',
  style: 'Code Style Changes',
  test: 'Tests',
  breakingChange: 'BREAKING CHANGES',
  break: 'BREAKING CHANGES'
};


module.exports.generate = (pkg, version, commits) => {

  let content = [];
  let date = new Date().toJSON().slice(0, 10);
  let heading = '##';

  let repoUrl;

  if (!commits) {
    tools.logWarning('Unable to find commits metadata to parse');
    return null;
  }

  heading += ' ' + version + ' (' + date + ')';

  content.push(heading);
  content.push('');

  let ISSUES_MANAGER_HOST;

  if (pkg.standalone) {
    ISSUES_MANAGER_HOST = configUtils.global.getConfigOptionsStandalone().ISSUES_MANAGER_HOST;
  } else {
    ISSUES_MANAGER_HOST = configUtils.global.getConfigOptions().ISSUES_MANAGER_HOST;
  }

  return Promise.resolve()
    .then(() => {
      return gitUtils.getRepoUrl(pkg.paths.root);
    })
    .then((repoUrlFound) => {
      repoUrl = repoUrlFound;
    })
    .then(() => {
      let types = {}

      commits.forEach((commit) => {
        let type = TYPES[commit.type] ? commit.type : DEFAULT_TYPE;

        if (commit.body && commit.body.indexOf('BREAKING CHANGE') !== -1) {
          type = 'breakingChange';
        }
        let category = commit.category ? commit.category : DEFAULT_CATEGORY;

        types[type] = types[type] || {};
        types[type][category] = types[type][category] || [];
        types[type][category].push(commit);
      })

      return types;
    })
    .then((rawTypes) => {
      let types = rawTypes;

      Object.keys(rawTypes).sort().forEach((type) => {

        content.push('##### ' + TYPES[type]);
        content.push('');

        Object.keys(rawTypes[type]).forEach(function (category) {
          let prefix = '*';
          let categoryHeading = prefix + (category ? ' **' + category + ':**' : '');

          content.push(categoryHeading);
          prefix = '  *';

          types[type][category].forEach(function (commit) {

            let shorthash = commit.hash.substring(0, 8);
            if (repoUrl) {
              shorthash = '[' + shorthash + '](' + repoUrl + '/commits/' + commit.hash + ')';
            }

            let issueString = '';
            if (commit.issue) {
              issueString += '[' + commit.issue + '](' + ISSUES_MANAGER_HOST + commit.issue + ') ';
            }

            content.push(prefix + ' ' + commit.subject + ' ' + issueString + ' (' + shorthash + ')');
          });
        });

      });
    })
    .then(() => {
      content.push('');
      content.push('* * *');
      content.push('* * *');
      content.push('');
      return content.join('\n');
    })
    .catch((e) => {
      throw e;
    });
}




module.exports.writeChangelog = (changelogContent, outputPath) => {
  return Promise.resolve()
    .then(() => {
      tools.logInfo('writing changelog markdown...');

      let changelogFile;

      if (!outputPath) {
        changelogFile = path.join(process.cwd(), 'CHANGELOG.md');
      } else {
        changelogFile = path.join(outputPath, 'CHANGELOG.md');
      }

      if (tools.isFileExists(changelogFile)) {
        const data = fs.readFileSync(changelogFile);
        const fd = fs.openSync(changelogFile, 'w+');
        const buffer = new Buffer(changelogContent);

        fs.writeSync(fd, buffer, 0, buffer.length, 0);
        fs.writeSync(fd, data, 0, data.length, buffer.length);
        fs.close(fd);

      } else {
        fs.writeFileSync(changelogFile, changelogContent);
      }
    })
}
