"use strict";

(function () {

  var async = require('async');
  var chalk = require('chalk');
  var childProcess = require('child_process');
  var fs = require('fs');
  var table = require('text-table');

  var fsp = require('../../utils/fs');
  var path = require('../../utils/path.js');
  var walk = require('../../utils/walk.js');

  var rFileStatus = /^([A-Z])\s+(.+)$/;

  var getConfig = function getConfig(configs, dirs) {
    var config = {};

    if (!dirs.length) {

      config = configs.root || {};
      config.baseDir = '.';

      return config;
    }

    config = configs[dirs.join(path.sep)];

    if (config) {

      config.baseDir = dirs.join(path.sep);

      return config;
    }

    return getConfig(configs, dirs.splice(0, dirs.length - 1));
  };

  var checkFiles = function checkFiles(files, options) {

    var dirname = process.cwd();

    var configs = {};

    async.each(fs.readdirSync(dirname), function (repo, callback) {

      var subdirname = path.join(dirname, repo);
      var efesconfig = path.join(dirname, repo, '.efesconfig');
      var data = void 0;

      if (repo === '.efesconfig') {

        data = fsp.readJSONSync(subdirname);
        if (data) {
          configs.root = data;
        }
      } else if (fs.existsSync(efesconfig)) {

        data = fsp.readJSONSync(efesconfig);
        if (data) {
          configs[repo] = data;
        }
      } else if (fs.statSync(subdirname).isDirectory()) {

        var regIncludes = [/\.efesconfig$/i];
        var regExcludes = [/node_modules/, /\.git/, /\.tmp/];

        walk(subdirname, regIncludes, regExcludes, function (err, subfiles) {

          if (err) {
            console.log(chalk.red(err.message));
            return;
          }
          subfiles.forEach(function (subrepo) {
            var data = fsp.readJSONSync(path.join(subdirname, subrepo));
            var _subrepo = [repo, path.dirname(subrepo)].join(path.sep);
            if (data) {
              configs[_subrepo] = data;
            }
          });
        });
      }

      callback();
    }, function () {

      if (!configs) {
        console.log('没有配置 Lint 监测规则！');
        return;
      }

      var filesLinted = 0;

      var lintErrors = 0;

      var imgErrors = [];

      var changedDir = [];

      files.some(function (fileStatus) {

        var _fileStatus = rFileStatus.exec(fileStatus);

        var filename = _fileStatus[2];
        var status = _fileStatus[1];

        var dirs = path.dirname(filename).split(path.sep);
        var config = getConfig(configs, dirs);
        var linter = config.lint;
        var suffix = path.extname(filename).slice(1);

        var _sublinter = null;

        if (/^(js|css)$/i.test(suffix) && linter) {
          _sublinter = linter[suffix];
        }

        if (changedDir.indexOf(config.baseDir) === -1) {
          changedDir.push(config.baseDir);
        }

        if (_sublinter) {
          filesLinted += 1;

          var _cmd = 'efes ' + _sublinter.engine + ' --color -f ' + filename + ' -c ' + path.join(process.cwd(), config.baseDir, _sublinter.config);

          var _stdout = childProcess.execSync(_cmd).toString();
          console.log(_stdout);
          lintErrors = _stdout.indexOf('problems') !== -1;
        }

        if (/^(x|d|s)?html?$/i.test(suffix)) {

          var _cmd2 = 'efes ver -f ' + filename + ' --color';

          childProcess.execSync(_cmd2, {
            stdio: 'inherit'
          });
        }

        if (/^(png|jpg|jpeg|gif)$/i.test(suffix)) {
          if (status !== 'A') {
            imgErrors.push(_fileStatus);
          }
        }
      });

      if (imgErrors.length > 0) {
        console.log(chalk.yellow("\n监测到下列图片有修改，请升级版本号后，重新 add 到 git 仓库中。\n"));

        var output = imgErrors.map(function (message) {
          var out = [];
          out.push(chalk.red(message[1]));
          out.push(message[2]);
          out.push(chalk.red('error'));
          return out;
        });

        output = table(output, {
          align: ['r', 'l']
        });

        output = output.split('\n').map(function (el) {
          return el.replace(/(\d+)\s+(\d+)/, function (m, p1, p2) {
            return chalk.grey(p1 + ':' + p2);
          });
        }).join('\n');
        console.log(output);
        console.log(chalk.red.bold('\n✖ ' + imgErrors.length + ' image version problems'));
      }

      if (filesLinted === 0) {
        console.log('没有文件需要执行 lint 检查。');
      } else if (!lintErrors) {
        console.log('\n' + chalk.white.bgGreen.bold('没有 lint 错误。'));
      }

      if (imgErrors.length === 0) {
        console.log('\n' + chalk.white.bgGreen.bold('没有 image 版本错误。'));
      }

      if (!lintErrors && imgErrors.length === 0) {
        console.log("\n" + chalk.white.bgGreen.bold('OKAY'));
      }

      return lintErrors;
    });
  };

  module.exports = function (options) {

    console.log('开始 commit 检查...');

    childProcess.exec('git diff --name-status HEAD', {
      cwd: process.cwd()
    }, function (err, stdout) {
      if (err) {
        console.log(chalk.bold('异常: ') + '没有 git 提交。');
      } else {
        if (stdout) {
          stdout = stdout.trim().split('\n');
          stdout = stdout.filter(function (fileStatus) {
            return fileStatus.indexOf('D') !== 0;
          });

          if (stdout.length) {
            checkFiles(stdout, options);
          } else {
            console.log('No files changed.');
          }
        } else {
          console.log('No files changed.');
        }
      }
    });
  };
})();