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

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

/**
 * 平十法数据
 */
export interface FlatTenData {
    problems: Array<{
        minuend: number; // 被减数
        subtrahend: number; // 减数
        result: number;
    }>;
}

/**
 * 平十法练习绘制服务
 */
class FlatTenDraw extends BaseDrawService {
    flatTenData: FlatTenData | null = null;

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

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

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

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

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

        // 绘制题目区域（3行3列）
        this.drawProblems(flatTenData.problems);
    }

    /**
     * 绘制口诀
     */
    private drawMnemonic() {
        const { ctx, canvasWidth } = this;
        const mnemonic = '看大数的个位，拆小数，连续减，算得数';
        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<{
            minuend: number;
            subtrahend: 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: { minuend: number; subtrahend: number; result: number },
    ) {
        const blueColor = '#8CBAFF';
        const yellowColor = '#FFCB05';
        const greenColor = '#5AE2B1';
        const pinkColor = '#F2A4C0';
        const lineColor = '#6CD2EA';

        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 minuendBoxX = centerX - boxSize - horizontalSpacing;
        const minusX = minuendBoxX + boxSize + horizontalSpacing;
        const subtrahendBoxX = minusX + horizontalSpacing;
        const equalsX = subtrahendBoxX + boxSize + horizontalSpacing - 2;
        const answerBoxX = equalsX + 10 + horizontalSpacing;

        // 绘制被减数方框
        this.drawTopLayerBox(
            ctx,
            minuendBoxX,
            firstLayerY,
            boxSize,
            problem.minuend,
            fontSize,
            blueColor,
        );

        // 绘制减号
        this.drawMinusSign(ctx, minusX, firstLayerY + boxSize / 2, 12);

        // 绘制减数方框
        this.drawTopLayerBox(
            ctx,
            subtrahendBoxX,
            firstLayerY,
            boxSize,
            problem.subtrahend,
            fontSize,
            yellowColor,
        );

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

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

        // 第二层：以减数为根节点拆分二叉树结构（两个空方框）
        // 减数拆分成两部分：第一部分 = 被减数的个位数，第二部分 = 减数 - 第一部分
        const secondLayerY = firstLayerY + boxSize + verticalSpacing;
        const subtrahendBoxCenterX = subtrahendBoxX + boxSize / 2;

        // 计算减数的拆分：第一部分是被减数的个位数，第二部分是减数减去第一部分
        const minuendOnes = problem.minuend % 10; // 被减数的个位数
        const part1 = minuendOnes; // 第一部分
        const part2 = problem.subtrahend - part1; // 第二部分

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

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

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

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

        // 第三层：在被减数正下方绘制一个方框
        const thirdLayerY = secondLayerY + boxSize + verticalSpacing + 15;
        const minuendBoxCenterX = minuendBoxX + boxSize / 2;
        const thirdBoxX = minuendBoxCenterX; // 第三层方框X轴是被减数方框的中点
        const minusX2 = minuendBoxX + boxSize;
        const minusX3 = subtrahendBoxCenterX;

        // 绘制第三层方框（空方框，应该是10）
        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(minuendBoxCenterX, firstLayerY + boxSize);
        ctx.lineTo(minuendBoxCenterX, layer2_5Y);
        ctx.stroke();

        // 计算相交点（第2.5层位置）
        const intersectionY = layer2_5Y;

        // 从第二层左侧的方框（左子节点）下绘制直角折线到相交点
        const leftNodeCenterX = leftNodeX + boxSize / 2;

        ctx.beginPath();
        ctx.moveTo(leftNodeCenterX, secondLayerY + boxSize);
        ctx.lineTo(leftNodeCenterX, intersectionY); // 垂直向下
        ctx.lineTo(minuendBoxCenterX, intersectionY); // 水平到相交点
        ctx.stroke();

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

        // 以被减数框的X轴+方框size为X轴向下绘制直线和第三层的方框相连
        const minuendRightX = minuendBoxX + boxSize;
        ctx.strokeStyle = '#888';

        ctx.beginPath();
        ctx.moveTo(minuendRightX, intersectionY);
        ctx.lineTo(minuendRightX, thirdLayerY); // 垂直向下到第三层
        ctx.stroke();

        // 从第二层右侧的方框（右子节点）下绘制直角折线连接第三层方框
        const rightNodeCenterX = rightNodeX + boxSize / 2;
        // ctx.strokeStyle = 'red';
        ctx.beginPath();
        ctx.moveTo(rightNodeCenterX, secondLayerY + boxSize);
        ctx.lineTo(rightNodeCenterX, thirdLayerY + boxSize / 2); // 垂直向下到第三层
        ctx.lineTo(thirdBoxX + boxSize, thirdLayerY + boxSize / 2); // 水平连接到第三层方框中心
        ctx.stroke();

        this.drawSymbol(minusX3, thirdLayerY + 2, '-', 12);
    }

    /**
     * 绘制第一层方框（边框1px，#999，无填充，显示数字）
     */
    private drawTopLayerBox(
        ctx: RenderingContext,
        x: number,
        y: number,
        size: number,
        number: number,
        fontSize: number,
        color: string,
    ) {
        // 绘制方框
        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 drawMinusSign(
        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.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 FlatTenDraw;
