import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { updateOrder } from "./taskBoardSlice";
import TaskCard from "./../../components/TaskBoard/TaskCard";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
import { Flipper } from "react-flip-toolkit";
import { focusOnTask } from "./taskBoardSlice";
import styled from "styled-components";
import TaskInput from "./../../components/TaskBoard/TaskInput";
import Divider from "./../../components/TaskBoard/Divider";
import NoTasks from "../../components/TaskBoard/NoTasks";

const TaskBoardContainer = styled.div`
    flex: 1 1 0;
    display: flex;
    min-width: 396px;
    flex-direction: column;
    align-items: center;
    overflow-y: scroll; // to enable scrolling by default for this flex-container only
`;

const EmptySpace = styled.div`
    display: flex;
    min-width: 10px;
    min-height: 10px;
    margin: 10px;
`;

export function TaskBoard() {
    const tasks = useSelector((state) => state.tasks.taskArray);
    const meta = useSelector((state) => state.tasks.meta);
    let focussedTask = meta.focussedTaskIndex !== -1 ? tasks[meta.focussedTaskIndex] : null;
    const dispatch = useDispatch();

    function handleOnDragEnd(result) {
        if (!result.destination) return;

        let items = [...tasks.map((i) => ({ ...i }))];
        const [reorderedItem] = items.splice(result.source.index, 1);
        items.splice(result.destination.index, 0, reorderedItem);

        let i = result.source.index;
        let direction = result.destination.index > result.source.index; // direction true means moving right & swapping
        // below is logic to reset globalKeys to maintain correct sort order.
        while (i != result.destination.index) {
            if (direction) {
                items[i].globalKey = tasks[i].globalKey;
                i++;
            } else {
                items[i].globalKey = tasks[i].globalKey;
                i--;
            }
            if (i == result.destination.index) {
                items[i].globalKey = tasks[i].globalKey;
            }
        }

        if (meta.focussedTaskIndex !== -1) {
            let greaterIndex = Math.max(result.destination.index, result.source.index);
            let smallerIndex = Math.min(result.destination.index, result.source.index);

            if (result.source.index === meta.focussedTaskIndex) {
                dispatch(focusOnTask(result.destination.index));
            } else if (meta.focussedTaskIndex >= smallerIndex && meta.focussedTaskIndex <= greaterIndex) {
                if (result.destination.index > result.source.index) {
                    dispatch(focusOnTask(meta.focussedTaskIndex - 1)); // -1
                } else {
                    dispatch(focusOnTask(meta.focussedTaskIndex + 1)); // +1
                }
            }
        }

        dispatch(updateOrder(items)); // order is imp. focus then updateOrder
    }

    function getFlipKey() {
        let flipKey = "";
        tasks.forEach((i) => {
            flipKey += `${i.globalKey}`;
        });
        flipKey += `${meta.completedTaskStartIndex}`;
        return flipKey;
    }

    function isFocussed(id) {
        if (focussedTask !== null && focussedTask.id === id) return true;
        return false;
    }

    // input has both onChange and onKeyDown - can be optimised by using one and combining

    return (
        <TaskBoardContainer>
            <TaskInput focussedTaskIndex={meta.focussedTaskIndex} />
            {tasks.length === 0 ? <NoTasks /> : tasks.length === meta.completedTasksCount && <NoTasks allCompleted={true} />}
            <Flipper flipKey={getFlipKey()}>
                <DragDropContext onDragEnd={handleOnDragEnd}>
                    <Droppable droppableId="dropArea">
                        {(provided) => (
                            <div {...provided.droppableProps} ref={provided.innerRef}>
                                {tasks.map((i, index) =>
                                    !i.isCompleted ? (
                                        <Draggable isDragDisabled={i.isCompleted} key={i.id} draggableId={`${i.id}`} index={index}>
                                            {(provided2) => (
                                                <TaskCard
                                                    focussedTaskIndex={meta.focussedTaskIndex}
                                                    focussedTaskGlobalKey={meta.focussedTaskIndex !== -1 ? tasks[meta.focussedTaskIndex].globalKey : -1}
                                                    taskIndex={index}
                                                    forwardRBDProvided={provided2}
                                                    task={i}
                                                    isFocussed={isFocussed(i.id)}
                                                />
                                            )}
                                        </Draggable>
                                    ) : (
                                        ""
                                    )
                                )}
                                {provided.placeholder}
                            </div>
                        )}
                    </Droppable>
                </DragDropContext>

                {meta.completedTaskStartIndex !== -1 && <Divider />}

                {meta.showCompletedTasks &&
                    tasks.map((i, index) =>
                        i.isCompleted ? (
                            <TaskCard
                                focussedTaskIndex={meta.focussedTaskIndex}
                                focussedTaskGlobalKey={meta.focussedTaskIndex !== -1 ? tasks[meta.focussedTaskIndex].globalKey : -1}
                                taskIndex={index}
                                key={i.id}
                                forwardRBDProvided={{ innerRef: null }}
                                task={i}
                                isFocussed={isFocussed(i.id)}
                            />
                        ) : (
                            ""
                        )
                    )}
            </Flipper>
            <EmptySpace />
        </TaskBoardContainer>
    );
}