import "../style/home/home.css"

import { Header } from "./template/Header"
import { BASE } from "../Constants"
import Draggable from "react-draggable";
import {NULL_POS} from "../components/arrows/Pos";
import {contains} from "../components/arrows/Box";
import React, {useRef, useState} from "react";
import { fetchAPI } from "../Fetcher"
import {User} from "../model/User";
import { FaShare } from "react-icons/fa";
import {SaveStates} from "../components/editor/SavingState";

interface Tactic {
    id: number
    name: string
    creation_date: string
}

interface Team {
    id: number
    name: string
    picture: string
    main_color: string
    second_color: string
}

export default function Home({
    lastTactics,
    allTactics,
    teams,
    user,
}: {
    lastTactics: Tactic[]
    allTactics: Tactic[]
    teams: Team[]
    user: User
}) {
    return (
        <div id="main">
            <Header user={user} />
            <Body
                lastTactics={lastTactics}
                allTactics={allTactics}
                teams={teams}
                user={user}
            />
        </div>
    )
}

function Body({
    lastTactics,
    allTactics,
    teams,
    user,
}: {
    lastTactics: Tactic[]
    allTactics: Tactic[]
    teams: Team[]
    user : User
}) {
    const widthPersonalSpace = 78
    const widthSideMenu = 100 - widthPersonalSpace
    return (
        <div id="body">
            <PersonalSpace width={widthPersonalSpace} allTactics={allTactics} teams={teams} user={user}/>
            <SideMenu
                width={widthSideMenu}
                lastTactics={lastTactics}
                teams={teams}
            />
        </div>
    )
}

function SideMenu({
    width,
    lastTactics,
    teams,
}: {
    width: number
    lastTactics: Tactic[]
    teams: Team[]
}) {
    return (
        <div id="side-menu" style={{
            width : width + "%",
        }}>
            <div id="side-menu-content">
                <TeamList teams={teams}/>
                <TacticList lastTactics={lastTactics}/>
            </div>
        </div>
    )
}

function PersonalSpace({
    width,
    allTactics,
    teams,
    user,
}: {
    width: number
    allTactics: Tactic[]
    teams : Team[]
    user : User
}) {
    return (
        <div
            id="personal-space"
            style={{
                width: width + "%",
            }}>
            <TitlePersonalSpace />
            <BodyPersonalSpace allTactics={allTactics} teams={teams} user={user}/>
        </div>
    )
}

function TitlePersonalSpace() {
    return (
        <div id="title-personal-space">
            <h2>Espace Personnel</h2>
        </div>
    )
}

function TableData({
    allTactics,
    teams,
    user,
}: {
    allTactics: Tactic[]
    teams : Team[]
    user : User
}) {
    const nbRow = Math.floor(allTactics.length / 3) + 1
    let listTactic = Array(nbRow)
    for (let i = 0; i < nbRow; i++) {
        listTactic[i] = Array(0)
    }
    let i = 0
    let j = 0
    allTactics.forEach((tactic) => {
        listTactic[i].push(tactic)
        j++
        if (j === 3) {
            i++
            j = 0
        }
    })

    i = 0
    while (i < nbRow) {
        listTactic[i] = listTactic[i].map((tactic: Tactic, i) => (
            <DraggableTableDataElement key={i} tactic={tactic} teams={teams}/>
        ))
        i++
    }
    if (nbRow == 1) {
        if (listTactic[0].length < 3) {
            for (let i = 0; i <= 3 - listTactic[0].length; i++) {
                listTactic[0].push(<td key={"tdNone" + i}></td>)
            }
        }
    }

    const data = listTactic.map((tactic, rowIndex) => (
        <tr key={rowIndex + "row"}>{tactic}</tr>
    ))
    return data
}


function DraggableTableDataElement({
    tactic,
    teams,
} : {
    tactic : Tactic
    teams : Team[]
}) {
    const ref = useRef<HTMLDivElement>(null)
    const [dragging, setDragging] = useState(false)
    const [hovered, setHovered] = useState(false);

    const handleButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
        event.stopPropagation();
        if (!dragging) {
            const userEmail = window.prompt("Entrez l'email à qui partager la tactique :");
            if(userEmail != null) {
                onShareTactic(userEmail, tactic);
            }
        } else {
            setDragging(false);
        }
    };

    return (
        <Draggable position={NULL_POS}
                   nodeRef={ref}
                   onDrag={() => setDragging(true)}
                   onStop={() => { if(dragging) {
                       onDropTactic(ref.current.getBoundingClientRect(), tactic, teams)
                   }
                   }}
        >
            <td key={tactic.id}
                ref={ref}
                className="data"
                onClick={() => { if(!dragging) {
                    location.pathname = BASE + "/tactic/" + tactic.id + "/edit"
                }
                else {
                    setDragging(false)
                }
                }}
                onMouseEnter={() => setHovered(true)}
                onMouseLeave={() => setHovered(false)}
            >

                {truncateString(tactic.name, 25)}
                {hovered && (
                    <div className="share-icon-container">
                        <button className="share-button share-icon-button" onClick={handleButtonClick}>
                            <FaShare className="share-icon" />
                        </button>
                    </div>
                    )}
            </td>
        </Draggable>
    )
}

function BodyPersonalSpace({
    allTactics,
    teams,
    user,
}: {
    allTactics: Tactic[]
    teams : Team[]
    user : User
}) {
    let data
    if (allTactics.length == 0) {
        data = <p>Aucune tactique créée !</p>
    } else {
        data = <TableData allTactics={allTactics} teams={teams} user={user}/>
    }

    return (
        <div id="body-personal-space">
            <table>
                <tbody key="tbody">{data}</tbody>
            </table>
        </div>
    )
}

function TeamList({ teams }: { teams: Team[] }) {
    return (
        <div id="teams">
            <div className="titre-side-menu">
                <h2 className="title">Mes équipes</h2>
                <button
                    className="new"
                    onClick={() => (location.pathname = BASE + "/team/new")}>
                    +
                </button>
            </div>
            <SetButtonTeam teams={teams} />
        </div>
    )
}

function TacticList({ lastTactics }: { lastTactics: Tactic[] }) {
    return (
        <div id="tactic">
            <div className="titre-side-menu">
                <h2 className="title">Mes dernières stratégies</h2>
                <button
                    className="new"
                    id="create-tactic"
                    onClick={() => (location.pathname = BASE + "/tactic/new")}>
                    +
                </button>
            </div>
            <SetButtonTactic tactics={lastTactics} />
        </div>
    )
}

function SetButtonTactic({ tactics }: { tactics: Tactic[] }) {
    const lastTactics = tactics.map((tactic, i) => (
        <ButtonLastTactic key={i} tactic={tactic} />
    ))
    return <div className="set-button">{lastTactics}</div>
}

function SetButtonTeam({ teams }: { teams: Team[] }) {
    const listTeam = teams.map((teams, i) => <ButtonTeam key={i} team={teams} />)
    return <div className="set-button">{listTeam}</div>
}

function ButtonTeam({ team }: { team: Team }) {
    const name = truncateString(team.name, 20)
    return (
        <div>
            <div
                id={"button-team-" + team.id}
                className="button-side-menu data"
                onClick={() => {
                    location.pathname = BASE + "/team/" + team.id
                }}>
                {name}
            </div>
        </div>
    )
}

function ButtonLastTactic({ tactic }: { tactic: Tactic }) {
    const name = truncateString(tactic.name, 20)
    return (
        <div
            id={"button" + tactic.id}
            className="button-side-menu data"
            onClick={() => {
                location.pathname = BASE + "/tactic/" + tactic.id + "/edit"
            }}>
            {name}
        </div>
    )
}

function truncateString(name: string, limit: number): string {
    if (name.length > limit) {
        name = name.substring(0, limit) + "..."
    }
    return name
}

function onDropTactic(ref : DOMRect, tactic : Tactic, teams : Team[]) {
    let shared = false;
    for (const team of teams) {
        if (contains(ref, document.getElementById(`button-team-${team.id}`)!.getBoundingClientRect())) {
            if (!shared) {
                shareTacticToTeam(tactic, team);
                shared = true;
            }
        }
    }
}

async function onShareTactic(email: string, tactic: Tactic) {
    const canShareResponse = await fetchAPI(`tactic/${tactic.id}/can-share`, tactic);
    if (canShareResponse.ok) {
        const shareToAccountResponse = await fetchAPI(`tactic/${tactic.id}/share-to-account`, email);
        if (!shareToAccountResponse.ok) {
            alert("Une erreur s'est produite lors du partage de la tactique avec ce compte");
        }
    } else {
        alert("Vous ne pouvez pas partager cette tactique");
    }
}


async function shareTacticToTeam(tactic : Tactic, team : Team) {
    const canShare = await fetchAPI(`tactic/${tactic.id}/can-share-to-team`, team).then((r) => r.ok)
    if(canShare && confirm("Etes-vous sûr de vouloir partager la tactique " + tactic.name + " avec l'équipe " + team.name)) {
        fetchAPI(`tactic/${tactic.id}/share-to-team`, team)
    }
    if(!canShare) {
        alert("Vous ne pouvez pas partager cette tactique à cette équipe")
    }
}
