const fs = require('fs');
const chalk = require('chalk');


const utils = require('./utils');
const linters = require('./linters');
const checkers = require('./checkers');
const config = require('./config');


/**
 * 文件语法检查
 *
 * @param  {Object}  parts 片段列表
 * @return {Promise}       promise
 */
const lintCmlFile = async (parts) => {
  let result = {};

  // 语法检查
  for (let partName of ['json', 'interface', 'template', 'script', 'style']) {
    let part = parts[partName];

    // 不存在的片段直接跳过
    if (!part) {
      continue;
    }

    switch (partName) {
      // 模板
      case 'template':
        if (result.json && result.json.obj) {
          result.template = await linters.templatelint(part, result.json.obj);
        }
        break;

      // 接口
      case 'interface':
        result['interface'] = await linters.scriptlint(part);
        break;

      // 脚本
      case 'script':
        result.script = await linters.scriptlint(part);
        break;

      // json
      case 'json':
        result.json = await linters.jsonlint(part);
        break;

      // 样式
      case 'style':
        result.style = await linters.stylelint(part);
        break;

      default:

        break;
    }
    result[partName] = result[partName] || {};
    result[partName].start = part.line;
    result[partName].type = part.type;
    result[partName].file = part.file;
    result[partName].platform = part.platformType;
  }

  return result;
}

/**
 * 文件逻辑检查
 *
 * @param  {Object}  lintedResult 语法校验后的结果
 * @param  {string}  filepath     文件路径
 * @return {Promise}              promise
 */
const checkFile = async (lintedResult, filepath) => {
  // 校验style
  checkers.style(lintedResult);

  // 校验json
  checkers.json(lintedResult);

  // 校验脚本
  checkers.script(lintedResult);

  // 模板校验 BEGIN
  if (
    lintedResult.template && lintedResult.template.ast &&
    lintedResult.script && lintedResult.script.ast &&
    lintedResult.json && lintedResult.json.obj
  ) {
    let templateChecker = new checkers.Template(filepath, lintedResult);
    lintedResult.template.messages.push(...templateChecker.check());
  }
  // 模板校验 END

  return lintedResult;
};

/**
 * 处理过程
 *
 * @param  {string}   filepath   文件路径
 * @return {Promise}             promise
 */
const checkFileContent = async (filepath) => {
  let parts = utils.getCmlParts(filepath);
  let result = await lintCmlFile(parts);
  result = await checkFile(result, filepath);

  return result;
};

/**
 * 检查CML文件格式
 *
 * @param  {string} filepath 文件路径
 * @return {Object}          校验结果
 */
const checkCMLFileSpecification = async (filepath) => {
  let platforms = config.getPlatforms();
  let result = {
    core: {
      messages: []
    }
  };
  if (new RegExp('([^/]*?)\.(' + platforms.join('|') + ')\.cml$', 'g').test(filepath)) {
    let interfaceFile = filepath.replace(new RegExp('\.(' + platforms.join('|') + ')\.cml$', 'g'), '.interface');
    if (!fs.existsSync(interfaceFile)) {
      result.core.messages.push(chalk.red('[error]') + ' file: ' + interfaceFile + ' is not exist!');
    }
    // cml多文件格式
    else {
      Object.assign(result, await checkFileContent(filepath));
    }
  }
  // cml单文件格式
  else {
    Object.assign(result, await checkFileContent(filepath));
  }
  return result;
}

/**
 * 检查接口文件规范
 *
 * @param  {string}  filepath 文件路径
 * @return {Promise}          promise
 */
const checkInterfaceFileSpecification = async (filepath) => {
  let {parts, messages} = utils.getInterfaceParts(filepath);
  let result = {};
  let keys = Object.keys(parts);

  if (messages.length == 0 && keys.length > 1) {
    for (let key in parts) {
      if (parts.hasOwnProperty(key)) {
        let part = parts[key];
        result[key] = await linters.scriptlint(part);
        result[key] = result[key] || {};
        result[key].start = part.line;
        result[key].type = part.type;
        result[key].file = part.file;
        result[key].platform = part.platformType;
      }
    }
    // 校验脚本
    checkers.script(result);
    return result;
  }
  else {
    return {
      core: {
        type: 'core',
        messages,
        file: filepath
      }
    };
  }
}

/**
 * 校验文件格式
 *
 * @param  {string}  filepath 文件路径
 * @param  {string}  filetype 文件类型
 * @return {Promise}          promise
 */
const checkFileSpecification = async (filepath, filetype) => {

  if (filetype == 'cml') {
    return checkCMLFileSpecification(filepath);
  }
  else if (filetype == 'interface') {
    return checkInterfaceFileSpecification(filepath);
  }
};


module.exports = checkFileSpecification;
module.exports.lintCmlFile = lintCmlFile;
module.exports.checkFile = checkFile;
