import * as React from "react";
import {Letter as LetterData, PlayerAndScore} from "word_grid";
import {ChangeEvent, JSX} from "react";
import {
    cellTypeToDetails,
    CellType,
    LocationType,
    PlayableLetterData,
    CoordinateData, TileDispatchActionType, TileDispatch,
} from "./utils";


export function TileSlot(props: { tile?: React.JSX.Element | undefined, location: CoordinateData, dispatch: TileDispatch }): React.JSX.Element {
    let isDraggable = props.tile !== undefined;

    function onDragStart(e: React.DragEvent<HTMLDivElement>) {
        e.dataTransfer.effectAllowed = "move";
        e.dataTransfer.setData("wordGrid/coords", JSON.stringify(props.location));
    }

    function onDrop(e: React.DragEvent<HTMLDivElement>) {
        const startLocation: CoordinateData = JSON.parse(e.dataTransfer.getData("wordGrid/coords"));
        const thisLocation = props.location;

        props.dispatch({action: TileDispatchActionType.MOVE, start: startLocation, end: thisLocation});
    }

    let className = "tileSpot";
    if (props.location.location === LocationType.GRID) {
        className += " ephemeral";
    }

    return <div className={className}
        draggable={isDraggable}
        onDragStart={onDragStart}
        onDrop={onDrop}
        onDragOver={(e) => {e.preventDefault()}}
    >
        {props.tile}
    </div>

}

export function Letter(props: { data: LetterData, letterUpdater?: (value: string) => void }): React.JSX.Element {

    function modifyThisLetter(value:string){
        props.letterUpdater(value);
    }


    function onBlankInput(e: ChangeEvent<HTMLInputElement>){
        let value = e.target.value.toUpperCase();
        if(value.length > 1){
            value = value[value.length - 1];
        } else if(value.length == 0){
            modifyThisLetter(value);
            return;
        }

        // Now check that it's a letter
        let is_letter = value.match("[A-Z]") != null;
        if(is_letter){
            modifyThisLetter(value);
        } else {
            // Cancel and do nothing
            e.preventDefault();
        }

    }

    if(props.data.is_blank && props.data.ephemeral) {
        return <div className="letter">
            <input className="blank-input" type="text" onChange={onBlankInput} value={props.data.text} />
            <div className="letter-points">{props.data.points}</div>
        </div>
    } else {
        let className = "text";
        if (props.data.is_blank) { // not ephemeral
            className += " prev-blank";
        }
        return <div className="letter">
            <div className={className}>{props.data.text}</div>
            <div className="letter-points">{props.data.points}</div>
        </div>
    }



}

export function TileTray(props: { letters: Array<PlayableLetterData>, trayLength: number, dispatch: TileDispatch }): React.JSX.Element {

    let elements: JSX.Element[] = [];
    for (let i=0; i<props.trayLength; i++) {
        elements.push(
            <TileSlot
                key={"empty" + i}
                location={{location: LocationType.TRAY, index: i}}
                dispatch={props.dispatch} />
        );
    }

    props.letters
        .filter((x) => {return x !== undefined;})
        .forEach((letter, i) => {
        if (letter.location === LocationType.TRAY) {
            elements[letter.index] =
                <TileSlot
                    tile={<Letter
                        data={letter}
                        letterUpdater={(value) => {
                            props.dispatch({action: TileDispatchActionType.SET_BLANK, blankIndex: i, newBlankValue: value})
                        }}
                    />}
                    key={"letter" + letter.index}
                    location={{location: LocationType.TRAY, index: letter.index}}
                    dispatch={props.dispatch} />

        }
    });

    return (
        <div className="tray">
            {elements}
        </div>
    )

}

export function Grid(props: {
        cellTypes: CellType[],
        playerLetters: Array<PlayableLetterData>,
        boardLetters: LetterData[],
        dispatch: TileDispatch}) {

    const elements = props.cellTypes.map((ct, i) => {
        const {className, text} = cellTypeToDetails(ct);

        let tileElement: JSX.Element;
        if (props.boardLetters[i] !== undefined) {
            tileElement = <Letter data={props.boardLetters[i]} />;
        } else {
            tileElement = <>
                <span>{text}</span>
                <TileSlot
                location={{location: LocationType.GRID, index: i}}
                dispatch={props.dispatch} /></>;
        }

        return <div key={i} className={"grid-spot " + className}>

            {tileElement}
        </div>;
    });

    props.playerLetters
        .filter((letter) => {return letter !== undefined})
        .forEach((letter, i) => {
        if (letter.location === LocationType.GRID) {
            const ct = props.cellTypes[letter.index];
            const {className, text} = cellTypeToDetails(ct);

            elements[letter.index] =
                <div key={"letter" + letter.index} className={"grid-spot " + className}>
                    <TileSlot
                        tile={<Letter
                            data={letter}
                            letterUpdater={(value) => {
                                props.dispatch({action: TileDispatchActionType.SET_BLANK, blankIndex: i, newBlankValue: value});
                            }}
                        />}
                        location={{location: LocationType.GRID, index: letter.index}}
                        dispatch={props.dispatch} />
                </div>;


        }
    });

    return <div className="board-grid">
        {elements}
    </div>
}

export function Scores(props: {playerScores: Array<PlayerAndScore>}){
    let elements = props.playerScores.map((ps, i) => {
        return <div key={ps.name}>
            <h3>{ps.name}</h3>
            <span>{ps.score}</span>
        </div>;
    });

    return <div className="scoring">
        {elements}
    </div>
}
