import Taro from '@tarojs/taro';
import { Canvas, View, Image } from '@tarojs/components';
import { useEffect, useRef, useState } from 'react';
import React from 'react';
import './Dial.scss'
import { useSelector } from 'react-redux';

const Component = (props) => {
    const [scenario] = useState(useSelector((state: any) => state.scenario))
    const [currentContext, setCurrentContext] = useState(null)
    const canvasWidth: number = 334;
    const canvasHeight: number = 334;
    const dpr = Taro.getSystemInfoSync().pixelRatio; // 获取设备的像素比
    const canvasRef = useRef<any>(null);
    const watchLineWidth = 300
    const canvasId = 'canvasDialId';

    var canStartDrag = false;
    var canEndDrag = false;
    var canRingDrag = false;

    var current = {
        start: global.startTime,
        end: global.endTime
    }

    var startCount = parseInt((current.start.split(':') as any)[0]) * 60 + parseInt((current.start.split(':') as any)[1]);
    var endCount = parseInt((current.end.split(':') as any)[0]) * 60 + parseInt((current.end.split(':') as any)[1]);
    var startAngle = (startCount / 1440) * 2 * Math.PI - Math.PI / 2;
    var endAngle = (endCount / 1440) * 2 * Math.PI - Math.PI / 2;
    endAngle = endAngle > startAngle ? endAngle : endAngle + 2 * Math.PI;

    var lastAngle;
    var lastDuration = 0;

    var strStart = current.start;
    var strEnd = current.end;

    var needDrawFastRing = false;
    if (scenario.name == 'FAST_SLEEP' && scenario.step == 'sleep') {
        needDrawFastRing = true;
    }

    useEffect(() => {

        const query = Taro.createSelectorQuery();
        query.select(`.${canvasId}`).fields({ node: true, size: true });
        query.exec((res) => {
            if (res[0] == null) return;
            const _canvas = res[0].node;
            _canvas.width = res[0].width * dpr;
            _canvas.height = res[0].height * dpr;
            global.canvas = _canvas
            const ctx = _canvas.getContext('2d');
            setCurrentContext(ctx)

            // 设置画布尺寸
            ctx.scale(dpr, dpr);


            drawCanvas(ctx);
        });
    }, []);

    const drawCanvas = (ctx: any) => {



        const centerX = canvasWidth / 2;
        const centerY = canvasHeight / 2;
        const radius = 140;//Math.min(centerX, centerY) - 38;

        ctx.clearRect(0, 0, canvasWidth, canvasHeight);

        //画断食环
        if (needDrawFastRing) {
            ctx.beginPath();
            ctx.arc(centerX, centerY, radius + 16 + 8, global.fast_start_angle, global.fast_end_angle);
            ctx.strokeStyle = 'rgba(170, 255, 0, 0.3)';
            ctx.lineWidth = 2;
            ctx.stroke();
        }

        // 绘制圆环
        ctx.beginPath();
        ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
        ctx.strokeStyle = "rgba(0,0,0,0.5)";
        ctx.lineWidth = 38;
        ctx.stroke();

        //绘制起终点圆弧
        ctx.beginPath();
        ctx.arc(centerX, centerY, radius, startAngle, endAngle);
        ctx.strokeStyle = canRingDrag ? "#3e3e3e" : "#1c1c1c";
        ctx.lineWidth = 38;
        ctx.lineCap = "round";
        ctx.stroke();


        //画刻度线
        ctx.save()
        ctx.beginPath()
        ctx.moveTo(centerX, centerY)

        ctx.arc(
            centerX, centerY, watchLineWidth / 2.0, startAngle, endAngle
        )

        ctx.clip()
        if (global.canvas_watch_line) {
            ctx.drawImage(global.canvas_watch_line, centerX - watchLineWidth / 2.0, centerY - watchLineWidth / 2.0, watchLineWidth, watchLineWidth)
        }
        else {
            let tempImage = global.canvas.createImage()
            tempImage.src = require('@/assets/images/watch_line.png')//'./watch_line.png'//'..//assets/images/watch_line.png'
            tempImage.onload = () => {
                global.canvas_watch_line = tempImage
                drawCanvas(ctx)
            }
        }
        ctx.restore()
        ctx.closePath()

        if (scenario.step == 'fast') {
            global.fast_start_angle = startAngle;
            global.fast_end_angle = endAngle;
        }

        const pointX = centerX + Math.cos(startAngle) * radius;
        const pointY = centerY + Math.sin(startAngle) * radius;

        //绘制起点圆点
        ctx.beginPath();
        ctx.arc(pointX, pointY, 17, 0, 2 * Math.PI);
        ctx.fillStyle = (canRingDrag || canStartDrag) ? "#3e3e3e" : "#1c1c1c";
        ctx.fill();

        //绘制起点图标
        // ctx.save()
        // ctx.beginPath()
        // ctx.translate(pointX, pointY)
        // ctx.rotate(startAngle)
        // ctx.translate(-pointX, -pointY)

        if (global.canvas_start_icon) {
            ctx.drawImage(global.canvas_start_icon, pointX - 20, pointY - 20, 40, 40)
        }
        else {
            let tempImage = global.canvas.createImage()
            tempImage.src = require('@/assets/images/wakeup-white.png')//'./watch_line.png'//'..//assets/images/watch_line.png'
            tempImage.onload = () => {
                global.canvas_start_icon = tempImage
                drawCanvas(ctx)
            }
        }

        // ctx.restore()
        // ctx.closePath()

        // 绘制终点圆点
        const pointX2 = centerX + Math.cos(endAngle) * radius;
        const pointY2 = centerY + Math.sin(endAngle) * radius;

        ctx.beginPath();
        ctx.arc(pointX2, pointY2, 17, 0, 2 * Math.PI);
        ctx.fillStyle = (canRingDrag || canEndDrag) ? "#3e3e3e" : "#1c1c1c";
        ctx.fill();

        //绘制终点图标
        if (global.canvas_end_icon) {
            ctx.drawImage(global.canvas_end_icon, pointX2 - 20, pointY2 - 20, 40, 40)
        }
        else {
            let tempImage = global.canvas.createImage()
            tempImage.src = require('@/assets/images/watch_end_white.png')//'./watch_line.png'//'..//assets/images/watch_line.png'
            tempImage.onload = () => {
                global.canvas_end_icon = tempImage
                drawCanvas(ctx)
            }
        }
    };


    global.updateDial = (start, end) => {
        var startCount = parseInt((start.split(':') as any)[0]) * 60 + parseInt((start.split(':') as any)[1]);
        var endCount = parseInt((end.split(':') as any)[0]) * 60 + parseInt((end.split(':') as any)[1]);
        startAngle = (startCount / 1440) * 2 * Math.PI - Math.PI / 2;
        endAngle = (endCount / 1440) * 2 * Math.PI - Math.PI / 2;
        endAngle = endAngle > startAngle ? endAngle : endAngle + 2 * Math.PI;
        drawCanvas(currentContext);
    }

    function twoPointDistance(p1, p2) {
        let dep = Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2));
        return dep;
    }

    function limitAngle(start, end) {
        var angle1 = start < 0 ? start + 2 * Math.PI : start;
        var angle2 = end < 0 ? end + 2 * Math.PI : end;
        if (angle2 < angle1) {
            angle2 = angle2 + 2 * Math.PI;
        }

        var leftAngle = angle2 - angle1;
        if (leftAngle > Math.PI * 23 / 12) {
            return 1;
        }
        else if (leftAngle < Math.PI / 12) {
            return 2;
        }
        return 0;
    }

    function durationAngle(end, start) {
        var angle1 = start < 0 ? start + 2 * Math.PI : start;
        var angle2 = end < 0 ? end + 2 * Math.PI : end;
        if (angle2 < angle1) {
            angle2 = angle2 + 2 * Math.PI;
        }

        return angle2 - angle1;
    }

    const handleTouchMove = (e: any) => {
        const ctx = currentContext;//canvasRef.current.getContext('2d');
        if (!canStartDrag && !canEndDrag && !canRingDrag) {
            drawCanvas(ctx);
            return;
        }


        const { x, y } = e.touches[0];

        let angle = Math.atan2(y - canvasWidth / 2.0, x - canvasWidth / 2.0)

        if (canStartDrag) {
            if (Math.abs(durationAngle(endAngle, angle) - lastDuration) > Math.PI) {
                //禁止跨越
                return;
            }

            var result = limitAngle(angle, endAngle);
            switch (result) {
                case 0:
                    startAngle = angle;
                    break;
                case 1:
                    startAngle = endAngle - 23 * Math.PI / 12;
                    break;
                case 2:
                    startAngle = endAngle - Math.PI / 12;
                    break;
            }

        }

        if (canEndDrag) {
            if (Math.abs(durationAngle(angle, startAngle) - lastDuration) > Math.PI) {
                //禁止跨越
                return;
            }

            var result = limitAngle(startAngle, angle);
            switch (result) {
                case 0:
                    endAngle = angle;
                    break;
                case 1:
                    endAngle = startAngle + 23 * Math.PI / 12;
                    break;
                case 2:
                    endAngle = startAngle + Math.PI / 12;
                    break;
            }

        }

        if (canRingDrag) {
            let delta = angle - lastAngle;
            startAngle += delta;
            endAngle += delta;
            lastAngle = angle;
        }

        startAngle = normalizeAngle(startAngle);
        endAngle = normalizeAngle(endAngle);

        angleToTime();

        drawCanvas(ctx);

        lastDuration = durationAngle(endAngle, startAngle);
    };

    function angleToTime() {
        var oldStart = parseInt(strStart.split(':')[0] as any) * 60 + parseInt(strStart.split(':')[1] as any);
        var oldEnd = parseInt(strEnd.split(':')[0] as any) * 60 + parseInt(strEnd.split(':')[1] as any);
        if (oldEnd < oldStart) oldEnd += 1440;
        var oldDuration = oldEnd - oldStart;


        var startCount = (startAngle + Math.PI / 2) / (2 * Math.PI) * 1440;
        var endCount = (endAngle + Math.PI / 2) / (2 * Math.PI) * 1440;
        startCount = startCount > 0 ? startCount : startCount + 1440;
        endCount = endCount > 0 ? endCount : endCount + 1440;

        startCount = roundToNearestFive(startCount);
        endCount = roundToNearestFive(endCount);

        var startHour = Math.floor(startCount / 60);
        var startMinute = Math.floor(startCount % 60);
        var endHour = Math.floor(endCount / 60);
        var endMinute = Math.floor(endCount % 60);
        startHour = startHour < 24 ? startHour : startHour - 24;
        endHour = endHour < 24 ? endHour : endHour - 24;
        var start = (startHour < 10 ? '0' + startHour : startHour) + ':' + (startMinute < 10 ? '0' + startMinute : startMinute);
        var end = (endHour < 10 ? '0' + endHour : endHour) + ':' + (endMinute < 10 ? '0' + endMinute : endMinute);

        if (canStartDrag) {
            strStart = start;
            global.updateDuration(start, strEnd);
        }
        else if (canEndDrag) {
            strEnd = end;
            global.updateDuration(strStart, end);
        }
        else if (canRingDrag) {
            var newCount = startHour * 60 + startMinute
            var newEnd = oldDuration + newCount

            const resultHour = Math.floor(newEnd / 60) % 24; // 对 24 取模以确保结果在 0-23 之间
            const resultMinute = newEnd % 60;

            strStart = start
            strEnd = `${String(resultHour).padStart(2, '0')}:${String(resultMinute).padStart(2, '0')}`;
            global.updateDuration(start, strEnd);
        }

    }

    function roundToNearestFive(minutes: number): number {
        const remainder = minutes % 5;
        if (remainder === 0) {
            return minutes;
        } else if (remainder < 3) {
            return minutes - remainder;
        } else {
            return minutes + (5 - remainder);
        }
    }

    const handleClick = (e) => {

        const scaleX = 1//dpr//canvasRect.width / canvasRect.width;
        const scaleY = 1//dpr//canvasRect.height / canvasRect.height;
        const canvasX = (e.touches[0].x - 0) * scaleX;
        const canvasY = (e.touches[0].y - 0) * scaleY;

        // 判断点击位置是否在圆点范围内
        const centerX = canvasWidth / 2;
        const centerY = canvasWidth / 2;
        const radius = Math.min(centerX, centerY) - 10;


        const pointX = centerX + Math.cos(startAngle) * radius;
        const pointY = centerY + Math.sin(startAngle) * radius;
        const distance = Math.sqrt(Math.pow(canvasX - pointX, 2) + Math.pow(canvasY - pointY, 2));
        if (distance <= 40) {
            canStartDrag = true;
        } else {
            canStartDrag = false;
        }

        const pointX2 = centerX + Math.cos(endAngle) * radius;
        const pointY2 = centerY + Math.sin(endAngle) * radius;
        const distance2 = Math.sqrt(Math.pow(canvasX - pointX2, 2) + Math.pow(canvasY - pointY2, 2));
        if (distance2 <= 40) {
            canEndDrag = true;
        } else {
            canEndDrag = false;
        }

        if (canStartDrag && canEndDrag) {
            if (distance < distance2) {
                canEndDrag = false
            }
            else {
                canStartDrag = false
            }
        }
        lastDuration = durationAngle(endAngle, startAngle);

        if (canStartDrag || canEndDrag) {
            drawCanvas(currentContext);
            canRingDrag = false;

            if (canStartDrag || canEndDrag){
                var type = canStartDrag?1:2
                global.startDuration(type)
            }
            return;
        }

        const distance3 = twoPointDistance({ x: canvasX, y: canvasY }, { x: centerX, y: centerY });
        let angle = Math.atan2(canvasY - canvasWidth / 2.0, canvasX - canvasWidth / 2.0)

        if (distance3 > 120 && distance3 < 190 && isCenterAngle(startAngle, angle, endAngle)) {
            canRingDrag = true;
        }
        lastAngle = angle;
        startAngle = normalizeAngle(startAngle);
        endAngle = normalizeAngle(endAngle);


        drawCanvas(currentContext);

        if (canStartDrag || canEndDrag || canRingDrag){
            var type = canStartDrag?1:canEndDrag?2:3
            global.startDuration(type)
        }
        else {
            global.endDuration()
        }
    };

    const normalizeAngle = (angle) => {
        if (angle < 0) {
            angle = angle + 2 * Math.PI;
            normalizeAngle(angle);
        }
        if (angle > 2 * Math.PI) {
            angle = angle - 2 * Math.PI;
            normalizeAngle(angle);
        }
        return angle;
    }

    const isCenterAngle = (start, center, end) => {
        start = normalizeAngle(start);
        center = normalizeAngle(center);
        end = normalizeAngle(end);
        if (start > end) {
            end += 2 * Math.PI;
        }
        if (end > 2 * Math.PI && center < start) {
            center += 2 * Math.PI;
        }
        return start < center && center < end;
    }

    const handleTouchEnd = (e) => {
        canStartDrag = false;
        canEndDrag = false;
        canRingDrag = false;
        global.endDuration()
        handleTouchMove(e)
    }

    return <View style={{ width: 334, height: 334, borderRadius: 167, backgroundColor: '#000', position: 'relative' }} ref={props.ref}>
        <Canvas canvasId={canvasId} id={canvasId} className={canvasId} type="2d"
            style={{ width: 334, height: 334, zIndex: 0 }}
            onTouchMove={handleTouchMove}
            onTouchEnd={handleTouchEnd}
            onTouchStart={handleClick}
            ref={canvasRef}
        />
        <View className='inner'>
            <Image src={require('@/assets/images/watch-inner.png')} style={{ width: 226, height: 226 }} />
        </View>
    </View>
}

export default React.memo(Component);