import {CSSProperties, useEffect, useRef, useState} from "react";
import "../style/editor.css";
import TitleInput from "../components/TitleInput";
import {BasketCourt} from "../components/editor/BasketCourt";

import {Rack} from "../components/Rack";
import {PlayerPiece} from "../components/editor/PlayerPiece";

import {Player} from "../tactic/Player";
import {Tactic, TacticContent} from "../tactic/Tactic";
import {fetchAPI} from "../Fetcher";
import {Team} from "../tactic/Team";
import {calculateRatio} from "../Utils";

const ERROR_STYLE: CSSProperties = {
    borderColor: "red",
}

export interface EditorViewProps {
    tactic: Tactic,
    onContentChange: (tactic: TacticContent) => Promise<boolean>,
    onNameChange: (name: string) => Promise<boolean>
}

/**
 * information about a player that is into a rack
 */
interface RackedPlayer {
    team: Team
    key: string
}

export default function Editor({tactic}: { tactic: Tactic }) {
    return <EditorView tactic={tactic}
                       onContentChange={(content: TacticContent) => (
                           fetchAPI(`tactic/${tactic.id}/save`, {content})
                               .then((r) => r.ok)
                       )}
                       onNameChange={(name: string) => (
                           fetchAPI(`tactic/${tactic.id}/edit/name`, {name})
                               .then((r) => r.ok)
                       )}/>
}

function EditorView({tactic: {name, content}, onContentChange, onNameChange}: EditorViewProps) {
    const [style, setStyle] = useState<CSSProperties>({});

    const positions = ["1", "2", "3", "4", "5"]
    const [allies, setAllies] = useState(
        positions.map((key) => ({ team: Team.Allies, key })),
    )
    const [opponents, setOpponents] = useState(
        positions.map((key) => ({ team: Team.Opponents, key })),
    )


    const [players, setPlayers] = useState<Player[]>(content.players);
    const courtDivContentRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        onContentChange({players})
            .then(success => {
                if (!success)
                    alert("error when saving changes.")
            })
    }, [players])

    const canDetach = (ref: HTMLDivElement) => {
        const refBounds = ref.getBoundingClientRect()
        const courtBounds = courtDivContentRef.current!.getBoundingClientRect()

        // check if refBounds overlaps courtBounds
        return !(
            refBounds.top > courtBounds.bottom ||
            refBounds.right < courtBounds.left ||
            refBounds.bottom < courtBounds.top ||
            refBounds.left > courtBounds.right
        )
    }

    const onPieceDetach = (ref: HTMLDivElement, element: RackedPlayer) => {
        const refBounds = ref.getBoundingClientRect()
        const courtBounds = courtDivContentRef.current!.getBoundingClientRect()


        const {x, y} = calculateRatio(refBounds, courtBounds)

        setPlayers(players => {
            return [...players, {
                id: players.length,
                team: element.team,
                role: element.key,
                rightRatio: x,
                bottomRatio: y
            }]
        })
    }

    return (
        <div id="main-div">
            <div id="topbar-div">
                <div>LEFT</div>
                <TitleInput style={style} default_value={name} on_validated={new_name => {
                    onNameChange(new_name).then(success => {
                        if (success) {
                            setStyle({})
                        } else {
                            setStyle(ERROR_STYLE)
                        }
                    })
                }}/>
                <div>RIGHT</div>
            </div>
            <div id="edit-div">
                <div id="racks">
                    <Rack
                        id="allies-rack"
                        objects={allies}
                        onChange={setAllies}
                        canDetach={canDetach}
                        onElementDetached={onPieceDetach}
                        render={({ team, key }) => (
                            <PlayerPiece team={team} text={key} key={key} />
                        )}
                    />
                    <Rack
                        id="opponent-rack"
                        objects={opponents}
                        onChange={setOpponents}
                        canDetach={canDetach}
                        onElementDetached={onPieceDetach}
                        render={({ team, key }) => (
                            <PlayerPiece team={team} text={key} key={key} />
                        )}
                    />
                </div>
                <div id="court-div">
                    <div id="court-div-bounds" ref={courtDivContentRef}>
                        <BasketCourt
                            players={players}
                            onPlayerChange={(player) => {
                                setPlayers(players => {
                                    const idx = players.indexOf(player)
                                    return players.toSpliced(idx, 1, player)
                                })
                            }}
                            onPlayerRemove={(player) => {
                                setPlayers((players) => {
                                    const idx = players.indexOf(player)
                                    return players.toSpliced(idx, 1)
                                })
                                switch (player.team) {
                                    case Team.Opponents:
                                        setOpponents((opponents) => [
                                            ...opponents,
                                            {
                                                team: player.team,
                                                pos: player.role,
                                                key: player.role,
                                            },
                                        ])
                                        break
                                    case Team.Allies:
                                        setAllies((allies) => [
                                            ...allies,
                                            {
                                                team: player.team,
                                                pos: player.role,
                                                key: player.role,
                                            },
                                        ])
                                }
                            }}
                        />
                    </div>
                </div>
            </div>
        </div>
    )
}
