import React, { useContext, useEffect, useRef, useState }from 'react';
import KaraokeLyric from './KaraokeLyric';
import {adjustCanvasScale, map, drawBackground} from '../function/canvasDefault';

interface Config {
    SRATE: number;
    fxmin: number;
    fxlow: number;
    fxhigh: number;
    fxmax: number;
}

interface PitchCanvasProps {
    pitchValue: number | null;
    targetPitch: number[];
    ballHistory: number[];
    size: number[];
    config: Config;
    // jsonHistory: number[];
    isPlaying: boolean;
}

const PitchCanvas: React.FC<PitchCanvasProps> = ({ config, isPlaying, size, pitchValue,targetPitch,ballHistory }) => {
    const { SRATE, fxmin, fxlow, fxhigh, fxmax } = config;
    const [ballY,setBallY] = useState<number>(size[0]);
    const canvasRef = useRef<HTMLCanvasElement>(null);
    const rectWidth = 5;
    const cornerRadius = 1;
    const desiredLength = Math.floor(size[1] / 5);
    const [jsonHistory, setJsonHistory] = useState<number[]>(new Array(desiredLength).fill(NaN));
    const [pitchY, setPitchY] = useState<number>(size[0]); 
    const newBallHistory = ballHistory.concat(Array(desiredLength - ballHistory.length).fill(NaN));
    const isPlayingRef = useRef(isPlaying);
    isPlayingRef.current = isPlaying; 
    const [jsonData, setJsonData] = useState(null);
    const [pitchArray, setPitchArray] = useState<number[]>([]);
    const intervalRef = useRef<NodeJS.Timer | null>(null);
    const [pitchArrayIndex, setPitchArrayIndex] = useState(0);
    const [colorChanges, setColorChanges] = useState<boolean[]>(new Array(desiredLength).fill(true));
    const [text, setText] = useState(""); 
    const [karaokePercentage, setKaraokePercentage] = useState(0); 
    const [updateCount, setUpdateCount] = useState(0);
    const [stop, setStop] = useState(false);
    const [textLength, setTextLength] = useState(0);
    const [showNotes, setShowNotes] = useState(false);
    // const middleOfCanvas = size[1] / 2;
    const blockStyle = {
        height: '100px', 
        backgroundColor: 'lightgray', 
        padding: '20px', 
        border: '1px solid #ccc', 
      };
    
    function updateBallY(value: number | null): void {
        if (value === null) {
            value = 0;
        }
        if (value == 0) {
            setBallY(size[0]);
        } else {
            setBallY(map(value, fxmin, fxmax, size[0], -1));
        }
    }
    // function drawBackground():void {
    //     const canvas = canvasRef.current;
    //     function adjustCanvasScale() {
    //         // 获取浏览器窗口的宽度
    //         const screenWidth = window.innerWidth;
    //         // 假设canvas的原始宽度是1000px
    //         const originalCanvasWidth = 1000;
    //         // 计算占窗口宽度80%时的缩放比例
    //         const scale = (screenWidth * 0.6) / originalCanvasWidth;
    //         // 应用缩放比例
    //         const canvas = document.querySelector('canvas');
    //         if (canvas) {
    //           canvas.style.transform = `scale(${scale})`;
    //           canvas.style.transformOrigin = 'top left';
    //         }
    //       }
    //     if (canvas) {
    //         const ctx = canvas.getContext('2d');
    //         if (ctx) {
    //             var gridSpacing = 50;
    //             ctx.strokeStyle = "#e0e0e0";
    //             for (var y = gridSpacing; y < canvas.height; y += gridSpacing) {
    //                 ctx.beginPath();
    //                 ctx.moveTo(0, y);
    //                 ctx.lineTo(canvas.width, y);
    //                 ctx.stroke();
    //             }

    //                         // Draw vertical line in the middle
    //         var middleX = canvas.width / 2; // Calculate the middle x coordinate
    //         ctx.beginPath();
    //         ctx.moveTo(middleX, 0); // Start at the top middle of the canvas
    //         ctx.lineTo(middleX, canvas.height); // Draw to the bottom middle of the canvas
    //         ctx.stroke(); // Render the line
        
    //             ctx.fillStyle = "#000";
    //             ctx.font = "12px Arial";
    //             for (var y = 0; y <= canvas.height; y += gridSpacing) {
    //                 var label = map(y, 0, canvas.height, fxmax, fxmin).toFixed(0);
    //                 ctx.fillText(label, 5, y + 12);
                    
    //             }
    //             adjustCanvasScale();
    //             window.addEventListener('resize', adjustCanvasScale);

    //         }
    //     }
    // }
    function parseTimeToSeconds(timeString: string): number  {
        // Parse the time string in the format "HH:MM:SS:FF" to seconds
        const parts = timeString.split(":");
        const hours = parseInt(parts[0], 10);
        const minutes = parseInt(parts[1], 10);
        const seconds = parseInt(parts[2], 10);
        const frames = parseInt(parts[3], 10);
        const frameDurationInSeconds = frames / 100;
    
        return hours * 3600 + minutes * 60 + seconds + frameDurationInSeconds;
    }
    
    function generatePitchArrayFromJson(jsonData: any[]): number[] {
        const pitchArray = [];
        
        const data = jsonData;
        let previousTimeInSeconds = 0;
        let previousPitch = 0;
    
        for (let i = 0; i < data.length; i++) {
            const currentTimeInSeconds = parseTimeToSeconds(data[i].time);
            const timeDifference = currentTimeInSeconds - previousTimeInSeconds;
    
            // Fill the array with the previous pitch value for the duration of timeDifference
            for (let j = 0; j < timeDifference * 100; j++) {
                pitchArray.push(previousPitch);
            }
    
            previousTimeInSeconds = currentTimeInSeconds;
            previousPitch = data[i].pitch;
        }
    
        // Ensure the array ends at the last time point
        const endTimeInSeconds = parseTimeToSeconds(data[data.length - 1].time);
        const endTimeDifference = endTimeInSeconds - previousTimeInSeconds;
        for (let j = 0; j < endTimeDifference * 100; j++) {
            pitchArray.push(previousPitch);
        }
    
        return pitchArray;
    }    

    useEffect(() => { 
        if((isPlayingRef.current)) {
            
        const canvas = canvasRef.current;
        if (canvas) {
            const ctx = canvas.getContext('2d');
            if (ctx) {
                // Clear the canvas
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                
                // Draw the background
                // drawBackground();
                drawBackground(canvasRef, fxmax, fxmin,showNotes);

                updateBallY(pitchValue);
                ctx.beginPath();
                // ctx.arc(size[1]/2, ballY, 10, 0, 2 * Math.PI);
                // ctx.arc(ballHistory.length * 5, ballY, 10, 0, 2 * Math.PI);
                ctx.arc(size[1]/2, ballY, 10, 0, 2 * Math.PI);

                const mappedJsonValue = map(jsonHistory[Math.floor(jsonHistory.length/2)], fxmin, fxmax, size[0], 0);
                const difference = Math.abs(mappedJsonValue - ballY);
                if (difference <= 30 && !isNaN(difference)) {
                    ctx.fillStyle = "green";
                } else {
                    ctx.fillStyle = "red";
                }

                ctx.fill();
                ctx.closePath();


                for (let i = 0; i < jsonHistory.length; i++) {
                    ctx.beginPath();
                    const mappedJsonValue = map(jsonHistory[i], fxmin, fxmax, size[0], 0);
                    if (colorChanges[i]) {
                        ctx.fillStyle = "green";
                    } else {
                        ctx.fillStyle = "rgba(0,255,255,0.5)";
                    }
                
                    ctx.fillRect(canvas.width - i * rectWidth, mappedJsonValue, rectWidth, rectWidth);
                    ctx.fill();
                    ctx.closePath();
                }
                ctx.stroke();
            }
        }
        // console.log(jsonHistory)
        }    
    }, [ballHistory, jsonHistory,isPlaying]);


    // first
    useEffect(() => {
        // fetch('http://127.0.0.1:8000/data/data_tes.json')
        fetch('http://127.0.0.1:8000/data/output.json')
        .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            
            return response.json();
        })
        .then(data => {
            const pitches = generatePitchArrayFromJson(data.data);
            setText(data.text);
            setPitchArray(pitches);            
        })
        .catch(error => {
            console.error('Error fetching the JSON file:', error);
        });

        // drawBackground();
        drawBackground(canvasRef, fxmax, fxmin,showNotes);
    },[]);
    useEffect(() => {
        setTextLength(pitchArray.length * 1.5);
      }, [pitchArray]); 
      const toggleShowNotes = () => {
        setShowNotes(!showNotes); 
        const canvas = canvasRef.current;
        if (canvas && canvas.getContext) {
            const ctx = canvas.getContext('2d');
            if (ctx) {
              // 清除画布
              ctx.clearRect(0, 0, canvas.width, canvas.height);
              // 立即调用drawBackground来重绘背景和标签
              drawBackground(canvasRef, fxmax, fxmin, !showNotes);
            }
          }
    }
      useEffect(() => {
          drawBackground(canvasRef, fxmax, fxmin, showNotes); // 确保在状态变化时重新绘制背景
        }, [showNotes]); 

    useEffect(() => {
        const intervalId = setInterval(() => {
            if (isPlaying) {
                let updatedHistory = [...jsonHistory];
    
                // Determine the value to be added (either from pitchArray or NaN)
                const valueToAdd = pitchArrayIndex < pitchArray.length
                    ? pitchArray[pitchArrayIndex]
                    : NaN;
                    if (!stop) { 
                        updatedHistory.pop();  // Remove the first element
                        updatedHistory.unshift(valueToAdd);  // Add the new value at the beginning
                        setJsonHistory(updatedHistory); 
                        setUpdateCount(updateCount => updateCount + 1);
                    }

                
                let updatedColor = [...colorChanges];
                const mappedJsonValue = map(jsonHistory[Math.floor(jsonHistory.length/2)], fxmin, fxmax, size[0], 0);
                const difference = Math.abs(mappedJsonValue - ballY);
                if (difference <= 30 && !isNaN(difference)) {
                    updatedColor[desiredLength/2] = true;
                } else {
                    updatedColor[desiredLength/2] = false;
                }
                if (!stop) {
                updatedColor.pop();
                updatedColor.unshift(false);
                setColorChanges(updatedColor);
                }


                if (pitchArrayIndex < pitchArray.length) {
                    setPitchArrayIndex(pitchArrayIndex + 1);
                }

            }
        }, 15);
        return () => clearInterval(intervalId);
        
    }, [jsonHistory, pitchArray, isPlaying, pitchArrayIndex, stop]);

    useEffect(() => {
        if (jsonHistory.every((value) => isNaN(value)) && pitchArrayIndex >= pitchArray.length/2 && pitchArray.length != 0 ) {
            // If not playing or all values are NaN, reset the update count
            setStop(true);
            console.log(pitchArray)
            console.log("Changed!!");
        }
    }, [jsonHistory, pitchArrayIndex]);
    
    useEffect(() => {
        if (isPlaying && pitchArray.length > 0) { 
            let newPercentage = 0;
            let tem = pitchArray.length;
            if (updateCount < desiredLength/2) {
                newPercentage = 0;
            } else {
                const overHalfIndex = updateCount -  desiredLength/2;
                if (overHalfIndex <= tem) { 
                    newPercentage = (overHalfIndex / tem) * 100;
                } else { 
                    newPercentage = 100;
                }
            }
            console.log( pitchArray.length )    
            setKaraokePercentage(newPercentage);
        }
    }, [ pitchArray, isPlaying, updateCount]);
    

    return (
        <div>
                <div style={blockStyle}>
                <KaraokeLyric text={text} percentage={karaokePercentage} />
    </div>    
            <canvas ref={canvasRef} onClick={toggleShowNotes} id="pitchCanvas" width="1000" height="500" style={{border: '1px solid #000'}}></canvas>
            </div>
        
    );
}

export default PitchCanvas;
