import { numberToChinese } from "../plugins/utils";
import {
  getModel as createFillQuestion,
  getFullModel as getFillQuesitonElements,
} from "../elements/fill-question/model";
import {
  getModel as createFillLine,
  getFullModel as getFillLineElements,
} from "../elements/fill-line/model";
import {
  getModel as createExplain,
  getFullModel as getExplainElements,
} from "../elements/explain/model";

const STRUCT_TYPES = {
  SINGLE_CHOICE: 1,
  MULTIPLE_CHOICE: 2,
  BOOLEAN_CHOICE: 3,
  FILL_BLANK: 4,
  TEXT: 5,
  NESTED: 6,
  LISTENING: 7,
  MATCHES: 8,
};

const COMMON_QUESTION_TYPES = [
  STRUCT_TYPES.SINGLE_CHOICE,
  STRUCT_TYPES.MULTIPLE_CHOICE,
  STRUCT_TYPES.BOOLEAN_CHOICE,
  STRUCT_TYPES.FILL_BLANK,
  STRUCT_TYPES.TEXT,
];
// TODO:  LISTENING: 7,MATCHES: 8,

const structTypeToCardElementType = {
  [STRUCT_TYPES.SINGLE_CHOICE]: "FILL_QUESTION",
  [STRUCT_TYPES.MULTIPLE_CHOICE]: "FILL_QUESTION",
  [STRUCT_TYPES.BOOLEAN_CHOICE]: "FILL_QUESTION",
  [STRUCT_TYPES.FILL_BLANK]: "FILL_LINE",
  [STRUCT_TYPES.TEXT]: "EXPLAIN",
};

const elementModel = {
  FILL_QUESTION: (presetData) => {
    const model = createFillQuestion(presetData);
    return getFillQuesitonElements(model, { pageSize: "A3", columnNumber: 2 });
  },
  FILL_LINE: (presetData) => {
    const model = createFillLine(presetData);
    return getFillLineElements(model, presetData.questions);
  },
  EXPLAIN: (presetData) => {
    const model = createExplain(presetData);
    return getExplainElements(model);
  },
};

function parseCommonPaperStruct(paperJson) {
  let structList = [];
  paperJson.details.forEach((detail) => {
    const commonQuestions = detail.questions.filter((q) =>
      COMMON_QUESTION_TYPES.includes(q.structType)
    );
    const commonStructList = getCommonQuestionStructList(
      detail,
      commonQuestions,
      true,
      0
    );
    structList.push(...commonStructList);

    const nestedQuestions = detail.questions.filter(
      (q) => !COMMON_QUESTION_TYPES.includes(q.structType)
    );
    const nestedStructList = getNestedQuestionStructList(
      detail,
      nestedQuestions
    );
    structList.push(...nestedStructList);
  });

  structList.sort((a, b) => a.sortNo - b.sortNo);
  console.log(structList);
  return structList;
}

function getCommonQuestionStructList(
  detail,
  questions,
  isCommon,
  nestedQNo = 0
) {
  let structList = [];
  let structs = {};
  const qTypeNum = isCommon ? 1 : 2;
  questions.forEach((question) => {
    if (!structs[question.structType]) structs[question.structType] = [];
    structs[question.structType].push(question);
  });
  Object.keys(structs).forEach((structType) => {
    const stype = structType * 1;
    const questions = parseCommonTypeQuestions(stype, structs[structType]);

    structList.push({
      detailName: detail.name,
      detailNo: detail.number,
      structType: stype,
      isCommon,
      nestedQNo,
      sortNo: stype * 10000 + detail.number * 1000 + qTypeNum * 100 + nestedQNo,
      questions,
    });
  });
  return structList;
}

function getNestedQuestionStructList(detail, questions) {
  let structList = [];
  questions.forEach((question) => {
    const qStructList = getCommonQuestionStructList(
      detail,
      question.subQuestions,
      false,
      question.number
    );
    structList.push(...qStructList);
  });
  return structList;
}

function parseCommonTypeQuestions(stype, dataList) {
  const choiceQs = [
    STRUCT_TYPES.SINGLE_CHOICE,
    STRUCT_TYPES.MULTIPLE_CHOICE,
    STRUCT_TYPES.BOOLEAN_CHOICE,
  ];
  let questions = [];
  if (choiceQs.includes(stype)) {
    questions = dataList.map((item) => {
      return {
        questionNo: item.number,
        optionCount:
          stype === STRUCT_TYPES.BOOLEAN_CHOICE ? 2 : item.options.length,
      };
    });
  } else if (stype === STRUCT_TYPES.FILL_BLANK) {
    questions = dataList.map((item) => {
      return {
        questionNo: item.number,
        fillCount: getFillBackClozeCount(item.body),
      };
    });
  } else {
    questions = dataList.map((item) => item.number);
  }
  return questions;
}

function getFillBackClozeCount(questionBody) {
  let num = 0;
  questionBody.sections.forEach((section) => {
    section.blocks.forEach((block) => {
      if (block.type === "cloze") num++;
    });
  });
  return num;
}

function buildCardElements(structList) {
  let cardElements = [];
  structList.forEach((struct) => {
    const detailChineseNumber = numberToChinese(struct.detailNo);
    let topicName = struct.isCommon
      ? `${detailChineseNumber}、${struct.detailName}`
      : `${detailChineseNumber}（${struct.nestedQNo}）`;
    const modelType = structTypeToCardElementType[struct.structType];

    if (!struct.isCommon && struct.structType === STRUCT_TYPES.TEXT) {
      struct.questions.forEach((qno) => {
        const tname = `${topicName}、${qno}`;

        const elements = elementModel[modelType]({
          questions: [""],
          topicName: tname,
        });
        cardElements.push(...elements);
      });
      return;
    }

    let presetData = {
      questions: struct.questions,
      topicName,
    };
    if (struct.structType === STRUCT_TYPES.MULTIPLE_CHOICE)
      presetData.isMultiply = true;
    if (struct.structType === STRUCT_TYPES.BOOLEAN_CHOICE)
      presetData.isBoolean = true;

    const elements = elementModel[modelType](presetData);
    cardElements.push(...elements);
  });

  return cardElements;
}

export function buildPaperCard(paperJson) {
  const structList = parseCommonPaperStruct(paperJson);
  const cardElements = buildCardElements(structList);
  console.log(cardElements);
  return cardElements;
}

// const paperStruct = {
//   paperName: "",
//   structList: [
//     {
//       detailName: "",
//       detailNo: 1,
//       structType: 1,
//       questions: [
//         { questionNo: "1", optionCount: 4 },
//         { questionNo: "2", optionCount: 4 },
//       ],
//     },
//     {
//       detailName: "",
//       detailNo: 1,
//       structType: 2,
//       questions: [
//         { questionNo: "3", optionCount: 4 },
//         { questionNo: "4", optionCount: 4 },
//       ],
//     },
//     {
//       detailName: "",
//       detailNo: 1,
//       structType: 3,
//       questions: [
//         { questionNo: "5", optionCount: 2 },
//         { questionNo: "6", optionCount: 2 },
//       ],
//     },
//     {
//       detailName: "",
//       detailNo: 1,
//       structType: 4,
//       questions: [
//         { questionNo: "7", fillCount: 1 },
//         { questionNo: "8", fillCount: 2 },
//       ],
//     },
//     {
//       detailName: "",
//       detailNo: 1,
//       structType: 5,
//       questions: ["11", "12"],
//     },
//   ],
// };
