import { Image, Button } from 'vant';
import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue';
import styles from './index.module.less';
import { useRect } from '@vant/use';
import { AnswerType, QuestionType } from '../../unit';
import AnserTitle from '../anser-title';
import AnswerAnalysis from '../answer-analysis';

// 单选和多选题
export default defineComponent({
  name: 'keep-look-question',
  props: {
    value: {
      type: Array,
      default: () => []
    },
    index: {
      // 题目是第几道
      type: Number,
      default: 1
    },
    data: {
      type: Object,
      default: () => ({})
    },
    /* 只读 */
    readOnly: {
      type: Boolean,
      default: false
    },
    showRate: {
      type: Boolean,
      default: false
    },
    showAnalysis: {
      // 是否显示解析
      type: Boolean,
      default: false
    },
    analysis: {
      type: Object,
      default: () => ({
        message: '',
        topic: false, // 是否显示结果
        userResult: true, // 用户答题对错
        disabled: false
      })
    }
  },
  emits: ['update:value'],
  setup(props, { emit, slots }) {
    const canvasRef = ref();
    const state = reactive({
      answerDomId: 'answer' + +new Date(),
      answerRect: {} as any,
      dpr: 1,
      sortable: null as any,
      list: [] as any,
      options: [] as any,
      drawLineList: [] as any,
      selectItem: [] as any
    });
    /*
    drawLineList 下的对象
      {
          startPoint: { x: 0, y: 0 },
          endPoint: { x: 0, y: 0},
          leftIndex: 1,
          rightIndex: 2
        }
    */
    const onLeftClick = (e: any, item: any) => {
      // 是否只读
      if (props.readOnly || props.analysis.disabled) return;
      state.options.forEach((option: any) => {
        if (!option.leftLocked && item.index !== option.index) {
          option.left = false;
        }
      });

      const selectd = isDrawLine(item.index, 'left');
      // 判断当前元素是否已经连线了
      if (selectd.status) {
        state.options.forEach((option: any) => {
          if (!option.rightLocked) {
            option.right = false;
          }
        });
        state.selectItem = [];
        // 如果已经连线了则去掉
        state.drawLineList.splice(selectd.selectIndex, 1);
        // 重新绘制
        renderDrawLine(canvasRef.value);

        state.options.forEach((option: any) => {
          if (selectd.selectOption.leftIndex === option.index) {
            option.left = false;
            option.leftLocked = false;
          }
          if (selectd.selectOption.rightIndex === option.index) {
            option.right = false;
            option.rightLocked = false;
          }
        });
      } else {
        item.left = !item.left;
        if (item.left) {
          // 为true时添加定位
          state.selectItem[0] = {
            index: item.index
          };
        } else {
          state.selectItem[0] = null;
        }

        // 判断是否有二个的关联
        if (state.selectItem[0] && state.selectItem[1]) {
          const postion = calcPoint();
          state.drawLineList.push(postion);
          state.selectItem = [];

          renderDrawLine(canvasRef.value);
        }
      }

      onSelect();
    };

    const onRightClick = (e: any, item: any) => {
      // 是否只读
      if (props.readOnly || props.analysis.disabled) return;
      // 去掉
      state.options.forEach((option: any) => {
        if (!option.rightLocked && item.index !== option.index) {
          option.right = false;
        }
      });
      const selectd = isDrawLine(item.index, 'right');

      // 判断当前元素是否已经连线了
      if (selectd.status) {
        state.options.forEach((option: any) => {
          if (!option.leftLocked) {
            option.left = false;
          }
        });
        state.selectItem = [];
        // console.log(
        //   selectd,
        //   'selected',
        //   JSON.stringify(state.drawLineList),
        //   state.drawLineList,
        //   state.drawLineList.length
        // )
        // 如果已经连线了则去掉
        state.drawLineList.splice(selectd.selectIndex, 1);
        // 重新绘制
        renderDrawLine(canvasRef.value);

        state.options.forEach((option: any) => {
          if (selectd.selectOption.leftIndex === option.index) {
            option.left = false;
            option.leftLocked = false;
          }
          if (selectd.selectOption.rightIndex === option.index) {
            option.right = false;
            option.rightLocked = false;
          }
        });
      } else {
        item.right = !item.right;

        if (item.right) {
          // 为true时添加定位
          state.selectItem[1] = {
            index: item.index
          };
        } else {
          state.selectItem[1] = null;
        }

        // 判断是否有二个的关联
        if (state.selectItem[0] && state.selectItem[1]) {
          const postion = calcPoint();
          state.drawLineList.push(postion);
          state.selectItem = [];
          renderDrawLine(canvasRef.value);
        }
      }

      onSelect();
    };

    /**
     * @description 判断是否已连接
     * @param key 选中的选项标识
     * @returns status 状态,  selectIndex 索引, selectOption 选中选项
     */
    const isDrawLine = (key: number, type = 'left') => {
      const drawLineList = state.drawLineList || [];
      let status = false; // true 连，false 没连
      let selectIndex = 0; // 连了所在的索引
      let selectOption: any = {};
      drawLineList.forEach((item: any, index: number) => {
        if (item.leftIndex === key && type === 'left') {
          selectOption = item;
          status = true;
          selectIndex = index;
        } else if (item.rightIndex === key && type === 'right') {
          selectOption = item;
          status = true;
          selectIndex = index;
        }
      });
      return {
        status,
        selectIndex,
        selectOption
      };
    };

    /**
     * @description 计算连线坐标位置及左右关联编号，每次计算坐标的时候都取元素最新位置定位
     * @returns 连线的坐标
     */
    const calcPoint = () => {
      const canvasPostion = useRect(canvasRef.value);
      const leftSectionItem = state.selectItem[0];
      const firstPostion: any = useRect(
        document.getElementById(leftSectionItem.index + '-left') as any
      );
      firstPostion.index = leftSectionItem.index;
      // console.log('🚀 ~ calcPoint ~ leftObj', leftObj)
      const rightSectionItem = state.selectItem[1];
      const secondPostion: any = useRect(
        document.getElementById(rightSectionItem.index + '-right') as any
      );
      secondPostion.index = rightSectionItem.index;
      console.log(state.selectItem, firstPostion, secondPostion);
      const startPoint = {
        x: firstPostion.width,
        y: firstPostion.top + firstPostion.height / 2 - canvasPostion.top
      };

      const endPoint = {
        x: secondPostion.left - canvasPostion.left,
        y: secondPostion.top + secondPostion.height / 2 - canvasPostion.top
      };

      state.options.forEach((item: any) => {
        if (item.index === firstPostion.index) {
          item.leftLocked = true;
        }
        if (item.index === secondPostion.index) {
          item.rightLocked = true;
        }
      });
      return {
        startPoint,
        endPoint,
        leftIndex: firstPostion.index,
        rightIndex: secondPostion.index
      };
    };

    /**
     * @description 绘制连线
     * @param canvasRef 对象
     */
    const renderDrawLine = (canvasRef: any) => {
      // 重新画线
      if (canvasRef.getContext) {
        // console.log(canvasRef.offsetWidth, canvasRef.offsetHeight)

        // 直接用 scale 放大整个坐标系，相对来说就是放大了每个绘制操作
        const ctx = canvasRef.getContext('2d');
        // ctx.scale(dpr, dpr)
        // ctx.scale(dpr, dpr)
        // canvasRef.width = canvasRef.offsetWidth
        // canvasRef.height = canvasRef.offsetHeight
        // width={state.answerRect.width * state.dpr || 0}
        // height={state.answerRect.height * state.dpr || 0}
        ctx.clearRect(
          0,
          0,
          state.answerRect.width * state.dpr || 0,
          state.answerRect.height * state.dpr || 0
        );
        state.drawLineList.forEach((item: any) => {
          drawLine(ctx, item.startPoint, item.endPoint);
        });
      }
    };

    /**
     * @description 连线
     * @param ctx canvas 对象
     * @param startPoint 开始坐标
     * @param endPoint 结束坐标
     * @returns void(0)
     */
    const drawLine = (ctx: any, startPoint: any, endPoint: any) => {
      ctx.beginPath();
      //  1 为了处理连线显示问题
      ctx.moveTo(
        Math.floor(startPoint.x - 1) * state.dpr,
        Math.ceil(startPoint.y) * state.dpr
      );
      ctx.lineTo(
        Math.ceil(endPoint.x + 1) * state.dpr,
        Math.ceil(endPoint.y) * state.dpr
      );
      ctx.lineWidth = 2 * state.dpr;
      ctx.strokeStyle = '#1CACF1';

      ctx.stroke();
    };

    // 返回选中的结果
    const onSelect = () => {
      const options = state.options || [];
      const drawLineList = state.drawLineList || [];
      const result: any = [];
      drawLineList.forEach((item: any) => {
        const leftOption = options.find(
          (child: any) => child.index === item.leftIndex
        );
        const rightOption = options.find(
          (child: any) => child.index === item.rightIndex
        );
        result.push({
          answerId: leftOption.index,
          answer: leftOption.leftValue,
          answerExtra: rightOption.rightValue
        });
      });
      emit('update:value', result);
    };

    const initOptions = () => {
      const answers = props.data.answers || [];
      const userAnswer = props.data.userAnswer || []; // 用户填写的答案
      // console.log(answers, '111')
      answers.forEach((answer: any) => {
        const tmp = {
          index: answer.examinationQuestionAnswerId, // 左边的值
          leftValue: answer.questionAnswer, // 左边的值
          rightValue: answer.questionExtra, // 右边的值
          leftType: answer.questionAnswerTypeCode || 'TXT', // 左边类型
          rightType: answer.questionExtraTypeCode || 'TXT', // 右边类型
          left: false, // 左边是否选中
          right: false, // 右边是否选中
          leftLocked: false, // 是否已经连线
          rightLocked: false // 是否已经连线
        };

        state.options.push(tmp);
      });

      // 反显答案-初始化数据
      // console.log(userAnswer)
      userAnswer.forEach((user: any) => {
        const temps: any = {
          startPoint: { x: 0, y: 0 },
          endPoint: { x: 0, y: 0 },
          leftIndex: 0,
          rightIndex: 0
        };
        state.options.forEach((option: any) => {
          // 左边状态
          if (option.index === user.answerId) {
            option.left = true;
            option.leftLocked = true;
            temps.leftIndex = option.index;
          }
          // 右边状态
          // console.log(option, user, '----')
          if (option.rightValue === user.answerExtra) {
            option.right = true;
            option.leftLocked = true;
            temps.rightIndex = option.index;
          }
        });
        state.drawLineList.push(temps);
      });

      // console.log(state.drawLineList, state.options)
      // 反显答案-连线
      nextTick(() => {
        state.drawLineList.forEach((draw: any) => {
          state.selectItem = [];
          const leftObj: any = useRect(
            document.getElementById(draw.leftIndex + '-left') as any
          );
          leftObj.index = draw.leftIndex;
          state.selectItem[0] = leftObj;
          const rightObj: any = useRect(
            document.getElementById(draw.rightIndex + '-right') as any
          );
          rightObj.index = draw.rightIndex;
          state.selectItem[1] = rightObj;
          const postion = calcPoint();
          draw.endPoint = postion.endPoint;
          draw.startPoint = postion.startPoint;
          state.selectItem = [];
        });
        setTimeout(() => {
          renderDrawLine(canvasRef.value);
        }, 100);
      });
    };

    onMounted(() => {
      initOptions();
      // 获取canvas 对象
      nextTick(() => {
        // 获取canvas元素定位
        const answer: any = document.getElementById(state.answerDomId);
        const answerRect = useRect(answer);
        state.answerRect = answerRect;

        const dpr = window.devicePixelRatio;
        state.dpr = dpr;
      });
    });

    return () => (
      <>
        <div class={styles.unitSubject}>
          {slots.title && slots.title()}
          {/* 标题 */}
          <AnserTitle
            index={props.index}
            name={props.data.name}
            score={props.data.totalScore}
            showRate={props.showRate}
            answerType={QuestionType.LINK}
            extra={{
              questionDetail: props.data.questionDetail,
              mediaUrls: props.data.mediaUrls,
              rightRate: props.data.rightRate
            }}
          />

          <div class={[styles.unitAnswers]} id={state.answerDomId}>
            <canvas
              ref={canvasRef}
              class={styles.canvasSection}
              width={state.answerRect.width * state.dpr || 0}
              height={state.answerRect.height * state.dpr || 0}
              style={{
                width: (state.answerRect.width || 0) + 'px',
                height: (state.answerRect.height || 0) + 'px'
              }}></canvas>
            {state.options.map((item: any) => (
              <div class={styles.answerItem}>
                <div
                  class={[styles.unitItem, item.left && styles.active]}
                  id={item.index + '-left'}
                  onClick={(e: any) => onLeftClick(e, item)}>
                  {item.leftType === AnswerType.TXT && item.leftValue}
                  {item.leftType === AnswerType.IMAGE && (
                    <Image src={item.leftValue} class={styles.img} />
                  )}
                </div>
                <div
                  class={[styles.unitItem, item.right && styles.active]}
                  id={item.index + '-right'}
                  onClick={(e: any) => onRightClick(e, item)}>
                  {item.rightType === AnswerType.TXT && item.rightValue}
                  {item.rightType === AnswerType.IMAGE && (
                    <Image src={item.rightValue} class={styles.img} />
                  )}
                </div>
              </div>
            ))}
          </div>
          <div class={styles.resetBtnGroup}>
            <Button
              round
              type="primary"
              disabled={props.readOnly || props.analysis.disabled}
              onClick={() => {
                state.drawLineList = [];
                renderDrawLine(canvasRef.value);

                // 清除所有的选中状态
                state.options.forEach((item: any) => {
                  item.left = false;
                  item.right = false;
                  item.leftLocked = false;
                  item.rightLocked = false;
                });
                // 清除所有的选择的内容
                state.selectItem = [];

                // 初始化数据
                onSelect();
              }}>
              重置
            </Button>
          </div>
        </div>

        {props.showAnalysis && (
          <AnswerAnalysis
            answerAnalysis={props.analysis.message}
            topic={props.analysis.topic}
            userResult={props.analysis.userResult}
          />
        )}
      </>
    );
  }
});
