import React, { FunctionComponent, useState, useEffect, ChangeEvent, MouseEvent } from "react";
import style from "./style.module.css";
import { Project } from "../../models/project";
import { newTask, Task, TaskID, EstimationConfidence } from "../../models/task";
import EditableText from "../../components/editable-text";
import { usePrintMediaQuery } from "../../hooks/use-media-query";
import { defaults, getTimeUnit } from "../../models/params";
import ProjectTimeUnit from "../../components/project-time-unit";

export interface TaskTableProps {
    project: Project
    onTaskAdd: (task: Task) => void
    onTaskRemove: (taskId: TaskID) => void
    onEstimationChange: (taskId: TaskID, confidence: EstimationConfidence, value: number) => void
    onTaskLabelUpdate: (taskId: TaskID, label: string) => void
}

export type EstimationTotals = { [confidence in EstimationConfidence]: number }

const TaskTable: FunctionComponent<TaskTableProps> = ({ project, onTaskAdd, onEstimationChange, onTaskRemove, onTaskLabelUpdate }) => {
    
    const defaultTaskCategory = Object.keys(project.params.taskCategories)[0];
    const [ task, setTask ] = useState(newTask("", defaultTaskCategory));
    const [ totals, setTotals ] = useState({
        [EstimationConfidence.Optimistic]: 0,
        [EstimationConfidence.Likely]: 0,
        [EstimationConfidence.Pessimistic]: 0,
    } as EstimationTotals);

    const isPrint = usePrintMediaQuery();

    useEffect(() => {
        let optimistic = 0;
        let likely = 0;
        let pessimistic = 0;

        Object.values(project.tasks).forEach(t => {
            optimistic += t.estimations.optimistic;
            likely += t.estimations.likely;
            pessimistic += t.estimations.pessimistic;
        });

        setTotals({ optimistic, likely, pessimistic });
    }, [project.tasks]);

    const onNewTaskLabelChange = (evt: ChangeEvent) => {
        const value = (evt.currentTarget as HTMLInputElement).value;
        setTask({...task, label: value});
    };

    const onNewTaskCategoryChange = (evt: ChangeEvent) => {
        const value = (evt.currentTarget as HTMLInputElement).value;
        setTask({...task, category: value});
    };

    const onTaskLabelChange = (taskId: TaskID, value: string) => {
        onTaskLabelUpdate(taskId, value);
    };

    const onAddTaskClick = (evt: MouseEvent) => {
        onTaskAdd(task);
        setTask(newTask("", defaultTaskCategory));
    };

    const onTaskRemoveClick = (taskId: TaskID, evt: MouseEvent) => {
        onTaskRemove(taskId);
    };

    const withEstimationChange = (confidence: EstimationConfidence, taskID: TaskID, evt: ChangeEvent) => {
        const textValue = (evt.currentTarget as HTMLInputElement).value;
        const value = parseFloat(textValue);
        onEstimationChange(taskID, confidence, value);
    };

    const onOptimisticChange = withEstimationChange.bind(null, EstimationConfidence.Optimistic);
    const onLikelyChange = withEstimationChange.bind(null, EstimationConfidence.Likely);
    const onPessimisticChange = withEstimationChange.bind(null, EstimationConfidence.Pessimistic);

    return (
        <div className="table-container">
            <table className={`table is-bordered is-striped is-hoverable is-fullwidth ${style.middleTable}`}>
                <thead>
                    <tr>
                        <th className={`${style.noBorder} noPrint`} rowSpan={2}></th>
                        <th className={style.mainColumn} rowSpan={2}>Tâche</th>
                        <th rowSpan={2}>Catégorie</th>
                        <th colSpan={3}>Estimation (en <ProjectTimeUnit project={project} />)</th>
                    </tr>
                    <tr>
                        <th>Optimiste</th>
                        <th>Probable</th>
                        <th>Pessimiste</th>
                    </tr>
                </thead>
                <tbody>
                    {
                        Object.values(project.tasks).map(t => {
                            const category = project.params.taskCategories[t.category];
                            const categoryLabel = category ? category.label : '???';
                            return (
                                <tr key={`taks-${t.id}`}>
                                    <td className={`is-narrow noPrint`}>
                                        <button
                                            onClick={onTaskRemoveClick.bind(null, t.id)}
                                            className="button is-danger is-small is-outlined">
                                        🗑️
                                        </button>
                                    </td>
                                    <td className={style.mainColumn}>
                                        <EditableText
                                            render={(value) => (<span>{value}</span>)}
                                            onChange={onTaskLabelChange.bind(null, t.id)}
                                            value={t.label} />
                                    </td>
                                    <td>{ categoryLabel }</td>
                                    <td>
                                        {
                                            isPrint ?
                                            <span>{t.estimations.optimistic}</span> :
                                            <input className="input" type="number" value={t.estimations.optimistic}
                                                min={0}
                                                onChange={onOptimisticChange.bind(null, t.id)} />
                                        }
                                    </td>
                                    <td>
                                        {
                                            isPrint ?
                                            <span>{t.estimations.likely}</span> :
                                            <input className="input" type="number" value={t.estimations.likely}
                                                min={0}
                                                onChange={onLikelyChange.bind(null, t.id)} />
                                        }
                                    </td>
                                    <td>
                                        {
                                            isPrint ?
                                            <span>{t.estimations.pessimistic}</span> :
                                            <input className="input" type="number" value={t.estimations.pessimistic}
                                                min={0}
                                                onChange={onPessimisticChange.bind(null, t.id)} />
                                        }
                                    </td>
                                </tr>
                            )
                        })
                    }
                    {
                        Object.keys(project.tasks).length === 0 ?
                        <tr>
                            <td className={`${style.noBorder} noPrint`}></td>
                            <td className={style.noTasks} colSpan={5}>Aucune tâche pour l'instant.</td>
                        </tr> :
                        null
                    }
                </tbody>
                <tfoot>
                    <tr>
                        <td className={`${style.noBorder} noPrint`}></td>
                        <td colSpan={2} className={isPrint ? style.noBorder : ''}>
                            <div  className="field has-addons noPrint">
                                <p className="control is-expanded">
                                    <input className="input" type="text" placeholder="Nouvelle tâche"
                                        value={task.label} onChange={onNewTaskLabelChange} />
                                </p>
                                <p className="control">
                                    <span className="select">
                                    <select onChange={onNewTaskCategoryChange} value={task.category}>
                                        {
                                            Object.values(project.params.taskCategories).map(tc => {
                                                return (
                                                <option key={`task-category-${tc.id}`} value={tc.id}>{tc.label}</option>
                                                );
                                            })
                                        }
                                    </select>
                                    </span>
                                </p>
                                <p className="control">
                                    <a className="button is-primary" onClick={onAddTaskClick}>
                                    Ajouter
                                    </a>
                                </p>
                            </div>
                        </td>
                        <th colSpan={3}>Total</th>
                    </tr>
                    <tr>
                        <td colSpan={isPrint ? 2 : 3} className={style.noBorder}></td>
                        <td>{totals.optimistic} <ProjectTimeUnit project={project} /></td>
                        <td>{totals.likely} <ProjectTimeUnit project={project} /></td>
                        <td>{totals.pessimistic} <ProjectTimeUnit project={project} /></td>
                    </tr>
                </tfoot>
            </table>
        </div>
    );
};

export default TaskTable;
