import { CARD_VERSION } from "../../enumerate";
import { deepCopy } from "../../plugins/utils";

const initIndex = {
  question: 1,
  absent: 1,
  paperType: 1,
  examNumber: 1,
  selective: 1,
  pageNumber: 1,
};
let fillAreaIndex = { ...initIndex };
let curPageOffsetInfo = {};

const VALID_ELEMENTS_FOR_EXTERNAL = [
  "LOCATOR",
  "BARCODE",
  "FILL_QUESTION",
  "FILL_LINE",
  "FILL_NUMBER",
  "FILL_FIELD",
  "FILL_TABLE",
  "LINES",
  "GRIDS",
];

function initFillAreaIndex() {
  fillAreaIndex = { ...initIndex };
}

function getFillAreaIndex(type) {
  return fillAreaIndex[type]++;
}

function getPreviewElementById(id) {
  return document.getElementById(`preview-${id}`);
}

function getOffsetInfo(dom) {
  const {
    width: domW,
    height: domH,
    left: domL,
    top: domT,
  } = dom.getBoundingClientRect();
  const {
    width: pageW,
    height: pageH,
    left: pageL,
    top: pageT,
  } = curPageOffsetInfo;

  const infos = [
    (domL - pageL) / pageW,
    (domT - pageT) / pageH,
    domW / pageW,
    domH / pageH,
  ];

  return infos.map((num) => num.toFixed(10) * 1);
}

// locator: [],
// barcode: [],
// info_area: [],
// fill_area: [],
// answer_area: []

const elementInfoFunc = {
  LOCATOR: (curPageDom) => {
    let tops = [];
    curPageDom.querySelector(".page-locator-top").childNodes.forEach((item) => {
      tops.push(getOffsetInfo(item));
    });

    let bottoms = [];
    curPageDom
      .querySelector(".page-locator-bottom")
      .childNodes.forEach((item) => {
        bottoms.push(getOffsetInfo(item));
      });
    return {
      top: tops,
      bottom: bottoms,
    };
  },
  BARCODE: (element) => {
    return {
      barcode: [
        {
          field: element.fields[0] && element.fields[0].code,
          area: getOffsetInfo(getPreviewElementById(element.id)),
        },
      ],
    };
  },
  FILL_QUESTION: (element) => {
    const dom = getPreviewElementById(element.id);
    const single = !element.isMultiply;
    const horizontal = element.optionDirection === "horizontal";

    let fillAreas = [];
    dom.querySelectorAll(".group-item").forEach((groupItem) => {
      let listInfos = [];

      groupItem
        .querySelectorAll(".question-item")
        .forEach((questionItem, questionIndex) => {
          let options = [];
          questionItem.childNodes.forEach((optionItem, optionIndex) => {
            if (optionIndex)
              options[optionIndex - 1] = getOffsetInfo(optionItem);
          });
          listInfos[questionIndex] = {
            main_number: element.topicNo,
            sub_number: questionItem.firstChild.textContent * 1,
            options,
            recog_info: [],
          };
        });
      fillAreas.push({
        field: "question",
        index: getFillAreaIndex("question"),
        single,
        horizontal,
        items: listInfos,
      });
    });

    return {
      fill_area: fillAreas,
    };
  },
  FILL_LINE: (element) => {
    const dom = getPreviewElementById(element.id);
    let sub_numbers = [];
    for (
      let i = element.startNumber,
        len = element.startNumber + element.questionsCount;
      i < len;
      i++
    ) {
      sub_numbers.push(i);
    }

    return {
      answer_area: [
        {
          main_number: element.topicNo,
          sub_number: sub_numbers.join(),
          area: getOffsetInfo(dom),
        },
      ],
    };
  },
  FILL_NUMBER: (element) => {
    let listInfos = [];
    const dom = getPreviewElementById(element.id);

    dom
      .querySelectorAll(".fill-number-list")
      .forEach((questionItem, questionIndex) => {
        let options = [];
        questionItem.childNodes.forEach((optionItem, optionIndex) => {
          options[optionIndex] = getOffsetInfo(optionItem);
        });
        listInfos[questionIndex] = {
          main_number: null,
          sub_number: null,
          options,
          recog_info: [],
        };
      });

    return {
      fill_area: [
        {
          field: "examNumber",
          index: getFillAreaIndex("examNumber"),
          single: true,
          horizontal: false,
          items: listInfos,
        },
      ],
    };
  },
  FILL_FIELD: (element) => {
    const dom = getPreviewElementById(element.id);

    return {
      info_area: [getOffsetInfo(dom)],
    };
  },
  FILL_TABLE: (element) => {
    const dom = getPreviewElementById(element.id);

    return {
      info_area: [getOffsetInfo(dom)],
    };
  },
  LINES: (element) => {
    const dom = getPreviewElementById(element.id);

    return {
      answer_area: [
        {
          main_number: null,
          sub_number: null,
          area: getOffsetInfo(dom),
        },
      ],
    };
  },
  GRIDS: (element) => {
    const dom = getPreviewElementById(element.id);

    return {
      answer_area: [
        {
          main_number: null,
          sub_number: null,
          area: getOffsetInfo(dom),
        },
      ],
    };
  },
};

function getPageNumberInfo() {
  const dom = document.getElementById(`preview-page-box-0`);
  let options = [];
  dom
    .querySelector(".page-number-rect-list")
    .childNodes.forEach((item, index) => {
      options[index] = getOffsetInfo(item);
    });
  return [
    {
      field: "pageNumber",
      index: 1,
      single: true,
      horizontal: true,
      items: [
        {
          main_number: null,
          sub_number: null,
          options,
          recog_info: [],
        },
      ],
    },
  ];
}

function getExtraInfo(pageDom) {
  const info = {
    barcode: [],
  };
  const courseBarDom = pageDom.querySelector(".course-barcode");
  if (courseBarDom) {
    info.barcode.push({
      field: "courseCode",
      area: getOffsetInfo(courseBarDom),
    });
  }

  return info;
}

function parsePageExchange(pages) {
  initFillAreaIndex();

  const npages = deepCopy(pages);

  curPageOffsetInfo = document
    .getElementById(`preview-page-box-0`)
    .getBoundingClientRect();
  const pageNumberInfo = pages.length > 2 ? getPageNumberInfo() : null;
  npages.forEach((page, pindex) => {
    const curPageDom = document.getElementById(`preview-page-box-${pindex}`);
    curPageOffsetInfo = curPageDom.getBoundingClientRect();

    let exchange = {
      card_type: 2,
      page_size: page.pageSize,
      page_image: "",
      locator: elementInfoFunc.LOCATOR(curPageDom),
      fill_locator: [],
      check_area: {
        black_line: [],
        white_line: [],
      },
      barcode: [],
      qrcode: [],
      ocr_area: [],
      info_area: [],
      fill_area: [],
      answer_area: [],
      extension: {
        barcode: [],
        fill_area: [],
        ocr_area: [],
        qrcode: [],
      },
    };
    const elements = [
      page.globals,
      ...page.columns.map((column) => column.elements),
    ];

    elements.forEach((elemGroup) => {
      elemGroup.forEach((element) => {
        if (!VALID_ELEMENTS_FOR_EXTERNAL.includes(element.type)) return;
        const info = elementInfoFunc[element.type](element);
        Object.entries(info).forEach(([key, vals]) => {
          exchange[key] = exchange[key].concat(vals);
        });
      });
    });

    if (!(pindex % 2) && pageNumberInfo) {
      let pnoInfo = deepCopy(pageNumberInfo);
      pnoInfo[0].index = getFillAreaIndex("pageNumber");
      exchange.fill_area = exchange.fill_area.concat(pnoInfo);
    }

    // 课程代码条码
    const extraInfo = getExtraInfo(curPageDom);
    Object.entries(extraInfo).forEach(([key, vals]) => {
      exchange.extension[key] = exchange.extension[key].concat(vals);
    });

    page.exchange = exchange;
  });

  return npages;
}

export function getPageModel({ cardConfig, pages }) {
  let npages = parsePageExchange(pages);
  return JSON.stringify(
    {
      version: CARD_VERSION,
      cardType: "FREE",
      cardConfig,
      pages: npages,
    },
    (k, v) => (k.startsWith("_") ? undefined : v)
  );
}
