import {
  getTmpDir,
  getInputDir,
  getOutputDir,
  getExtraDir,
  getImgDecodeTool,
  makeDirSync
} from "./env";
import { randomCode, formatDate } from "./utils";
const fs = require("fs");
const path = require("path");
const childProcess = require("child_process");
const gm = require("gm").subClass({
  imageMagick: true,
  appPath: getExtraDir("imagemagick/")
});

/**
 *  解析图片code信息
 * @param {String} imgPath 图片路径
 * @param {Object} codeArea code所在文件区域信息
 */
function decodeImageCode(imgPath, codeArea) {
  const tmpFile = path.join(
    getTmpDir(),
    `${formatDate("YYYYMMDDHHmmss")}_${randomCode(8)}.jpg`
  );

  const imgObj = gm(imgPath);

  // 裁剪条形码区域
  imgObj.crop(codeArea.width, codeArea.height, codeArea.x, codeArea.y);
  // 旋转
  const rotate = parseInt(codeArea.codeRotate);
  if (rotate) imgObj.rotate("#FFFFFF", rotate);

  return new Promise((resolve, reject) => {
    // 写入临时文件
    imgObj.write(tmpFile, function(err) {
      if (err) {
        reject("条形码临时文件获取失败");
        return;
      }
      // 获取条形码解析工具
      const exec = getImgDecodeTool();
      // 解析条形码
      let code;
      try {
        const DecodeResult = childProcess.execSync(`${exec} ${tmpFile}`);
        const codes = DecodeResult.toString()
          .replace(/\r/, "")
          .replace(/\n/, "")
          .split(":");
        if (codes.length <= 2) {
          code = codes[codes.length - 1].replace(/\s+/g, "");
        }
      } catch (e) {
        reject("解析条形码错误");
        return;
      }
      // 暂时不删除临时文件
      // fs.unlink(tmpFile, () => {});

      resolve(code);
    });
  });
}

/**
 * 旋转图片，并保存为正式文件
 * @param {*} imgPath 图片路径
 * @param {String} paperInfo 保持文件名称
 * @param {Object} collectConfig 裁剪区域
 */
async function saveOutputImage(imgPath, paperInfo, collectConfig) {
  const outputFormalPath = saveFormalImage(imgPath, paperInfo);
  const outputSlicelPath = await saveSliceImage(
    imgPath,
    paperInfo,
    collectConfig
  ).catch(() => {});

  if (outputSlicelPath && outputFormalPath)
    return { outputSlicelPath, outputFormalPath };
  return Promise.reject("试卷保存失败");
}

function saveFormalImage(imgPath, paperInfo) {
  const outputFormalPath = getOutputImagePath(paperInfo, "formal");
  fs.copyFileSync(imgPath, outputFormalPath);
}

function saveSliceImage(imgPath, paperInfo, collectConfig) {
  const outputSlicelPath = getOutputImagePath(paperInfo, "slice");
  const { codeArea, coverArea, tailorArea, imageRotate } = collectConfig;

  // slice图：完整处理流程
  let imgObj = gm(imgPath);
  // 条形码覆盖区
  imgObj
    .fill("#FFFFFF")
    .drawRectangle(
      codeArea.x,
      codeArea.y,
      codeArea.x + codeArea.width,
      codeArea.y + codeArea.height
    );

  // 保密覆盖区
  imgObj
    .fill("#FFFFFF")
    .drawRectangle(
      coverArea.x,
      coverArea.y,
      coverArea.x + coverArea.width,
      coverArea.y + coverArea.height
    );

  // 边缘裁切
  imgObj.crop(tailorArea.width, tailorArea.height, tailorArea.x, tailorArea.y);

  // 旋转
  if (imageRotate) imgObj.rotate("#FFFFFF", imageRotate);
  return new Promise((resolve, reject) => {
    imgObj.write(outputSlicelPath, function(err) {
      if (err) {
        reject(err);
      }
      resolve(outputSlicelPath);
    });
  });
}

function getOutputImagePath({ workId, subjectId, examNumber }, type) {
  const outputDir = path.join(getOutputDir(type), workId, subjectId);
  if (!fs.existsSync(outputDir)) makeDirSync(outputDir);
  return path.join(outputDir, examNumber + ".jpg");
}

/**
 * 获取最早添加的文件
 * @param {String} dir 图片目录
 */
function getEarliestFile(dir) {
  const ddir = dir || getInputDir();
  const files = fs
    .readdirSync(ddir)
    .filter(fileName => fileName.toLowerCase().match(/\.(jpg|png|jpeg)/))
    .map(fileName => {
      return {
        name: fileName,
        time: fs.statSync(path.join(ddir, fileName)).birthtimeMs
      };
    })
    .sort((a, b) => a.time - b.time);

  if (!files.length) return { url: "", name: "" };

  return {
    url: path.join(ddir, files[0].name),
    name: files[0].name
  };
}

export { decodeImageCode, saveOutputImage, getEarliestFile };
