import React from "react";
import { html } from "htm";
import * as Store from "./store.js";
import * as Tone from "./tone.js";
/** @typedef {({children}:{children?:preact.ComponentChildren})=>preact.VNode} BasicElement */
/** @type {({children, icon, light, disabled, inactive, onClick}:{children:preact.VNode, icon?:preact.VNode, light:boolean, disabled:boolean, inactive:boolean, onClick:()=>void})=>preact.VNode} */
export function Button({children, icon, light, disabled, inactive, onClick})
{
    const [FlashGet, FlashSet] = React.useState(0);
    const handleClick =()=>
    {
        if(inactive||disabled){ return; }
        FlashSet(FlashGet+1);
        onClick();
    };
    return html`
    `;
}
/** @type {BasicElement} */
export const Select =()=>
{
    const [State, Dispatch] = Store.Consumer();
    /** @type {(e:Event)=>void} */
    const handleChange =(e)=> Dispatch({Name:"Test", Data:parseInt(/** @type {HTMLSelectElement}*/(e.target).value)});
    return html`
    
        
        
    
`;
}
/** @type {BasicElement} */
export const Grade =()=>
{
    const [State] = Store.Consumer();
    const grade = Store.Grade(State.Live.Test);
    return html`
        Complete: ${grade.Done} of ${grade.Total}
        Accuracy: ${grade.Score}%
        
     `
};
/** @type {BasicElement} */
export const Controls =()=>
{
    const [State, Dispatch] = Store.Consumer();
    const [pulsedGet, pulsedSet] = React.useState(true);
    const [playGet, playSet] = React.useState(0);
    React.useEffect(()=>
    {
        /** @type {number|undefined} */
        let timer;
        if(playGet == 1)
        {
            const volNorm = (State.Stim.Value-State.Stim.Min)/(State.Stim.Max-State.Stim.Min);
            Tone.Play(!pulsedGet, State.Chan.Value, Store.ColumnMapping[State.Freq.Value][0], (volNorm*0.8) + 0.1);
            if(State.Live.Freq)
            {
                const testMark = State.Live.Freq[/** @type {"TestL"|"TestR"}*/(`Test${State.Chan.Value ? "R":"L"}`)];
                const handler = testMark.Stim <= State.Stim.Value ? ()=>{playSet(2)} : ()=>{playSet(0)}
                timer = setTimeout(handler, 500 + Math.random()*1000);
            }
        }
        return () => clearTimeout(timer);
        
    }, [playGet]);
    return html`
    <${Grade}/>
    
        Channel
        ${State.Chan.Value}
        <${Button} light=${State.Chan.Value == 0} inactive=${State.Chan.Value == 0} onClick=${()=>Dispatch({Name:"Chan", Data:-1})}>Left/>
        <${Button} light=${State.Chan.Value == 1} inactive=${State.Chan.Value == 1} onClick=${()=>Dispatch({Name:"Chan", Data:1})}>Right/>
    
 
    
        Frequency
        ${Store.ColumnMapping[State.Freq.Value][0]}
        <${Button} disabled=${State.Freq.Value == State.Freq.Min} onClick=${()=>Dispatch({Name:"Freq", Data:-1})}>-/>
        <${Button} disabled=${State.Freq.Value == State.Freq.Max} onClick=${()=>Dispatch({Name:"Freq", Data:1})}>+/>
    
 
    
        Stimulus
        ${State.Stim.Value}
        <${Button} disabled=${State.Stim.Value == State.Stim.Min} onClick=${()=>Dispatch({Name:"Stim", Data:-1})}>-/>
        <${Button} disabled=${State.Stim.Value == State.Stim.Max} onClick=${()=>Dispatch({Name:"Stim", Data:1})}>+/>
    
 
    
        Tone
        <${Button} onClick=${()=>{pulsedSet(true)}} light=${pulsedGet} inactive${pulsedGet}>Pulsed/>
        <${Button} onClick=${()=>{pulsedSet(false)}} light=${!pulsedGet} inactive${!pulsedGet}>Continuous/>
    
 
    
        Present
        
        <${Button} onClick=${()=>playSet(1)} disabled=${playGet==1} icon=${html`
`}>Play/>
    
 
    
        Mark
        <${Button} onClick=${()=>Dispatch({Name:"Mark", Data:true })} icon=${html`<${Mark} right=${State.Chan.Value} response=${true}  x="0" y="0" classes="stroke(white 2 draw) w-2 h-2 translate-x-1/2 translate-y-1/2"/>`}>Response/>
        <${Button} onClick=${()=>Dispatch({Name:"Mark", Data:false})} icon=${html`<${Mark} right=${State.Chan.Value} response=${false} x="0" y="0" classes="stroke(white 2 draw) w-2 h-2 translate-x-1/2 translate-y-1/2"/>`}>No Response/>
        <${Button}
        icon=${html`
`}
        onClick=${()=>Dispatch({Name:"Mark", Data:null })}
        disabled=${State.Live.Mark == undefined}>Clear/>
    
 
    `;
};
/** @type {BasicElement} */
export const Audiogram =()=>
{
    const [State] = Store.Consumer();
    const testMarksL = State.Draw.TestL.Points.map(p=>html`<${Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${false}/>`);
    const userMarksL = State.Draw.UserL.Points.map(p=>html`<${Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${false} classes=${State.Live.Mark == p.Mark ? "stroke-bold":""}/>`);
    const testMarksR = State.Draw.TestR.Points.map(p=>html`<${Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${true} />`);
    const userMarksR = State.Draw.UserR.Points.map(p=>html`<${Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${true} classes=${State.Live.Mark == p.Mark ? "stroke-bold":""}/>`);
    const testLinesL = State.Draw.TestL.Paths.map( p=>html``);
    const userLinesL = State.Draw.UserL.Paths.map( p=>html``);
    const testLinesR = State.Draw.TestR.Paths.map( p=>html``);
    const userLinesR = State.Draw.UserR.Paths.map( p=>html``);
    return html`
    
    
    
    
    
    `;
};
/** @type {BasicElement} */
export function Chart({children})
{
    const [State] = Store.Consumer();
    const inset = 20;
    /** @type {Array} */
    const rules = [];
    Store.ColumnMapping.forEach(([label, position, normal])=>
    {
        rules.push(html`
        
            ${label}
        `
        );
    });
    for(let db = State.Stim.Min; db <= State.Stim.Max; db+=10)
    {
        rules.push(html`
        
            ${db}
        `
        );
    }
    return html`
    
        
            Frequency in Hz
            
                
                    Hearing Level (dbHL)
                
            
            
         
     `;
}
/** @type {Record} */
const Glyph = {
    Arrow:()=> html`
    
    
    `,
    X: ({children})=> html`
    
    
    ${children}`,
    O: ({children})=> html`
    
    ${children}`
};
/** @type {({right, response, x, y, classes}:{right:boolean, response?:boolean, x:number|string, y:number|string, classes:string})=>preact.VNode} */
export const Mark =({right, response, x, y, classes})=>
{
    return html`
    `;
};