/**
 * 凑十法练习绘制服务
 */

import { BaseDrawService } from '../../../core/draw/baseDraw';

/**
 * 凑十法数据
 */
export interface MakeTenData {
    problems: Array<{
        left: number;
        right: number;
        result: number;
    }>;
}

/**
 * 凑十法练习绘制服务
 */
class MakeTenDraw extends BaseDrawService {
    makeTenData: MakeTenData | null = null;

    constructor(
        canvas: Canvas,
        ctx: RenderingContext,
        options?: Record<string, any>,
    ) {
        super(canvas, ctx, options);
        this.makeTenData = null;
    }

    /**
     * 绘制凑十法练习内容
     */
    async draw(makeTenData: MakeTenData) {
        if (!makeTenData || !makeTenData.problems) {
            return;
        }

        this.makeTenData = makeTenData;
        this.prepareDraw();
        await this.drawHeaderAndDivider();

        // 绘制口诀区域
        this.drawMnemonic();

        // 绘制虚线分割
        this.drawDashedDivider(this.currentY + 5, 40, '#999', 1);
        this.currentY += 20;

        // 绘制题目区域（5行4列）
        this.drawProblems(makeTenData.problems);
    }

    /**
     * 绘制口诀
     */
    private drawMnemonic() {
        const { ctx, canvasWidth } = this;
        const mnemonic = '看大数，拆小数，凑成10，加剩数';
        const fontSize = 24; // 适合小朋友的字体大小

        // 使用适合小朋友的字体
        ctx.font = `bold ${fontSize}px "YouYuan", "PingFang SC", "Microsoft Yahei", sans-serif`;
        ctx.fillStyle = '#343434';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';

        // 居中绘制口诀
        const mnemonicY = this.currentY + 30;
        ctx.fillText(mnemonic, canvasWidth / 2, mnemonicY);

        // 更新当前Y位置
        this.currentY = mnemonicY + 30;
    }

    /**
     * 绘制题目区域（3行3列）
     */
    private drawProblems(
        problems: Array<{ left: number; right: number; result: number }>,
    ) {
        const { ctx, canvasWidth } = this;
        const rows = 3;
        const cols = 3;
        const startX = 10;
        const startY = this.currentY + 20;
        const itemWidth = (canvasWidth - startX * 2) / cols - 18;
        const itemHeight = 200; // 每个题目的高度（增加高度以容纳三层结构）

        for (let row = 0; row < rows; row++) {
            for (let col = 0; col < cols; col++) {
                const index = row * cols + col;
                if (index >= problems.length) {
                    break;
                }

                const problem = problems[index];
                const x = startX + col * itemWidth;
                const y = startY + row * itemHeight;
                // 绘制单个题目
                this.drawSingleProblem(
                    ctx,
                    x,
                    y,
                    itemWidth,
                    itemHeight,
                    problem,
                );
            }
        }
    }

    /**
     * 绘制单个题目
     */
    private drawSingleProblem(
        ctx: RenderingContext,
        x: number,
        y: number,
        width: number,
        _height: number,
        problem: { left: number; right: number; result: number },
    ) {
        const blueColor = '#8CBAFF';
        const yellowColor = '#FFCB05';
        const greenColor = '#5AE2B1';
        const pinkColor = '#F2A4C0';
        const lineColor = '#6CD2EA';

        // 确定大数和小数
        const bigNumber = Math.max(problem.left, problem.right);
        const smallNumber = Math.min(problem.left, problem.right);
        const bigFirst = problem.left >= problem.right;

        const boxSize = 30; // 方框大小
        const fontSize = 18; // 数字字体大小
        const verticalSpacing = 25; // 垂直间距（缩小）
        const nodeSpacing = 40; // 二叉树节点之间的水平间距
        const horizontalSpacing = 10; // 第一层元素之间的水平间距

        // 第一层：原计算题
        const firstLayerY = y + 15;
        const centerX = x + width / 2;

        // 计算第一个加数的位置（大数或小数，取决于顺序）
        const firstNumber = bigFirst ? bigNumber : smallNumber;
        const secondNumber = bigFirst ? smallNumber : bigNumber;

        // 第一层元素位置（间距为15）
        const firstBoxX = centerX - boxSize - horizontalSpacing;
        const plusX = firstBoxX + boxSize + horizontalSpacing;
        const secondBoxX = plusX + horizontalSpacing;
        const equalsX = secondBoxX + boxSize + horizontalSpacing - 2;
        const answerBoxX = equalsX + 10 + horizontalSpacing;

        // 绘制第一个加数方框（边框1px，#999，无填充）
        this.drawTopLayerBox(
            ctx,
            firstBoxX,
            firstLayerY,
            boxSize,
            firstNumber,
            fontSize,
            blueColor,
        );

        // 绘制加号
        this.drawPlusSign(ctx, plusX, firstLayerY + boxSize / 2, 12);

        // 绘制第二个加数方框
        this.drawTopLayerBox(
            ctx,
            secondBoxX,
            firstLayerY,
            boxSize,
            secondNumber,
            fontSize,
            yellowColor,
        );

        // 绘制等号
        this.drawEqualsSign(ctx, equalsX, firstLayerY + boxSize / 2, 12);

        // 绘制答案框（空白）
        this.drawSquareBox(ctx, answerBoxX, firstLayerY, boxSize, greenColor);

        // 第二层：在较小加数下绘制二叉树结构（两个空方框）
        const secondLayerY = firstLayerY + boxSize + verticalSpacing;
        const smallBoxX = bigFirst ? secondBoxX : firstBoxX;
        const smallBoxCenterX = smallBoxX + boxSize / 2;

        // 绘制二叉树的两个子节点（空方框）
        const leftNodeX = smallBoxCenterX - nodeSpacing / 2 - boxSize / 2;
        const rightNodeX = smallBoxCenterX + nodeSpacing / 2 - boxSize / 2;

        // 绘制左子节点（空方框）
        this.drawSquareBox(ctx, leftNodeX, secondLayerY, boxSize, blueColor);

        // 绘制右子节点（空方框）
        this.drawSquareBox(ctx, rightNodeX, secondLayerY, boxSize, pinkColor);

        // 确定哪个子节点与小数相连
        // 如果小数在前（bigFirst=false），第二个方框（右子节点）和加数相连
        // 如果小数在后（bigFirst=true），第一个方框（左子节点）和加数相连
        const connectedNodeX = bigFirst ? leftNodeX : rightNodeX;
        const connectedNodeCenterX = connectedNodeX + boxSize / 2;
        const unconnectedNodeX = bigFirst ? rightNodeX : leftNodeX;
        const unconnectedNodeCenterX = unconnectedNodeX + boxSize / 2;

        // 绘制连接线（从较小加数到两个子节点）
        ctx.strokeStyle = lineColor;
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.moveTo(smallBoxCenterX, firstLayerY + boxSize);
        ctx.lineTo(leftNodeX + boxSize / 2, secondLayerY);
        ctx.stroke();

        ctx.beginPath();
        ctx.moveTo(smallBoxCenterX, firstLayerY + boxSize);
        ctx.lineTo(rightNodeX + boxSize / 2, secondLayerY);
        ctx.stroke();

        const thirdLayerY = secondLayerY + boxSize + verticalSpacing + 15;

        let bigBoxX = 0;
        let bigBoxCenterX = 0;
        let thirdBoxX = 0;
        let thirdLineEndX = 0;
        let firstPlusX = 0;
        let secondPlusX = 0;
        let thirdBoxCenterX = 0;
        if (bigFirst) {
            bigBoxX = firstBoxX;
            bigBoxCenterX = bigBoxX + boxSize / 2;
            thirdBoxX = bigBoxCenterX;
            thirdBoxCenterX = thirdBoxX + boxSize / 2;

            firstPlusX = bigBoxX + boxSize;
            secondPlusX = secondBoxX + boxSize / 2;

            thirdLineEndX = thirdBoxX + boxSize;
        } else {
            bigBoxX = secondBoxX;
            bigBoxCenterX = bigBoxX + boxSize / 2;
            thirdBoxX = bigBoxX - boxSize / 2;
            thirdBoxCenterX = thirdBoxX + boxSize / 2;

            firstPlusX = secondBoxX;
            secondPlusX = firstBoxX + boxSize / 2;
            thirdLineEndX = thirdBoxX;
        }

        // 绘制第三层方框（空方框）
        this.drawSquareBox(ctx, thirdBoxX, thirdLayerY, boxSize, blueColor);

        // 从较大加数正下方绘制直线至第2.5层的位置
        const layer2_5Y =
            secondLayerY +
            boxSize +
            (thirdLayerY - secondLayerY - boxSize) / 2 +
            4;
        ctx.strokeStyle = '#888';
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.moveTo(bigBoxCenterX, firstLayerY + boxSize);
        ctx.lineTo(bigBoxCenterX, layer2_5Y);
        ctx.stroke();

        // 计算相交点（第2.5层位置，在bigBoxCenterX处）
        const intersectionY = layer2_5Y;
        // ctx.strokeStyle = 'red';
        // 从第二层与小数相连的方框下绘制直角折线到相交点
        ctx.beginPath();
        ctx.moveTo(connectedNodeCenterX, secondLayerY + boxSize);
        ctx.lineTo(connectedNodeCenterX, intersectionY); // 垂直向下
        ctx.lineTo(bigBoxCenterX, intersectionY); // 水平到相交点
        ctx.stroke();

        // 绘制相交点到第三层方框的直线
        ctx.beginPath();
        ctx.moveTo(thirdBoxCenterX, intersectionY);
        ctx.lineTo(thirdBoxCenterX, thirdLayerY); // 水平到相交点
        ctx.stroke();

        // 在相交位置绘制小加号（使用drawSymbol方法）
        this.drawSymbol(firstPlusX, layer2_5Y - 10, '+', 12);

        // ctx.strokeStyle = 'blue';
        // 从第二层另一个方框（未与小数相连的）下绘制直角折线连接第三层方框
        ctx.beginPath();
        ctx.moveTo(unconnectedNodeCenterX, secondLayerY + boxSize);
        ctx.lineTo(unconnectedNodeCenterX, thirdLayerY + boxSize / 2); // 垂直向下到第三层
        ctx.lineTo(thirdLineEndX, thirdLayerY + boxSize / 2); // 水平连接到第三层方框中心
        ctx.stroke();

        // 在第二层另一个方框和第三层方框之间的折线中间绘制加号
        this.drawSymbol(secondPlusX, thirdLayerY + 2, '+', 12);
    }

    /**
     * 绘制第一层方框（边框1px，#999，无填充，显示数字）
     */
    private drawTopLayerBox(
        ctx: RenderingContext,
        x: number,
        y: number,
        size: number,
        number: number,
        fontSize: number,
        color: string,
    ) {
        // 绘制方框边框（1px，#999，无填充）
        // ctx.strokeStyle = '#999';
        // ctx.lineWidth = 1;
        // ctx.setLineDash([]);
        // ctx.strokeRect(x, y, size, size);
        this.drawSquareBox(ctx, x, y, size, color);

        // 绘制数字
        ctx.fillStyle = '#000';
        ctx.font = `bold ${fontSize}px "YouYuan", "PingFang SC", "Microsoft Yahei", sans-serif`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText(String(number), x + size / 2, y + size / 2);
    }

    /**
     * 绘制加号
     */
    private drawPlusSign(
        ctx: RenderingContext,
        x: number,
        y: number,
        size: number,
    ) {
        ctx.strokeStyle = '#000';
        ctx.lineWidth = 1.5;
        ctx.beginPath();
        // 横线
        ctx.moveTo(x - size / 2, y);
        ctx.lineTo(x + size / 2, y);
        // 竖线
        ctx.moveTo(x, y - size / 2);
        ctx.lineTo(x, y + size / 2);
        ctx.stroke();
    }

    /**
     * 绘制等号
     */
    private drawEqualsSign(
        ctx: RenderingContext,
        x: number,
        y: number,
        size: number,
    ) {
        ctx.strokeStyle = '#000';
        ctx.lineWidth = 1.5;
        ctx.beginPath();
        // 上横线
        ctx.moveTo(x, y - size / 3);
        ctx.lineTo(x + size, y - size / 3);
        // 下横线
        ctx.moveTo(x, y + size / 3);
        ctx.lineTo(x + size, y + size / 3);
        ctx.stroke();
    }
}

export default MakeTenDraw;
