import { Box, Image, Flex } from '@mantine/core';
import { DragDropContext, Draggable } from 'react-beautiful-dnd';
import { IconGripVertical } from '@tabler/icons-react';
import { StrictModeDroppable } from './StrictModeDroppable';
import { ActionIcon, Button, Center, Group, NumberInput, Paper, Text } from '@mantine/core';
import { IconTrash } from '@tabler/icons-react';
import { useEffect, useState } from 'react';
import ModalFileSelector from '../files/file-selector';
import API from '../../services/api';
import setNotification from '../errors/error-notification';
import GrantAccess, { Perm, checkPerm } from '../../tools/grant-access';
import { useAuth } from '../../tools/auth-provider';
import { parseTime } from '../../tools/timeUtil';

const Content = ({ form, playlistId, playlist }) => {
    const [fileSelector, setFileSelector] = useState(false);
    const toggleFileSelector = () => setFileSelector(!fileSelector);
    const [canEdit, setCanEdit] = useState(false);
    const { user } = useAuth();

    useEffect(() => {
        if (!user || !playlist) return;
        const canEditTmp = checkPerm(Perm.EDIT_PLAYLIST, user, playlist);
        if (canEditTmp != canEdit) {
            setCanEdit(canEditTmp);
        }
        return () => {};
    }, [playlist, user]);

    const handleAddFiles = (files) => {
        let formFiles = form.values.files;
        let max_position = formFiles[formFiles.length - 1]?.position ?? 0;
        files.forEach((file) => {
            max_position++;

            file.position = max_position;
            file.seconds = 10;
            const index = form.values.files.length;
            form.insertListItem('files', file);
            API.playlists
                .addFile(playlistId, { position: file.position, file_id: file.id, seconds: file.seconds })
                .then((res) => {
                    if (res.status !== 200) {
                        setNotification(true, `Error when adding file (${res.status})`);
                    }
                })
                .catch((err) => {
                    console.log('here');
                    form.removeListItem('files', index);
                    setNotification(true, err);
                });
        });
    };

    const changePositionValue = (from, to) => {
        return new Promise((resolve, reject) => {
            const formFiles = form.values.files;
            let below_position = to === 0 ? 0 : formFiles[to].position;
            let above_position = formFiles[to].position;
            if (to > from) {
                if (to === formFiles.length - 1) {
                    // last element so nothing above
                    above_position = formFiles.length + 1;
                } else {
                    // not last to taking element above
                    above_position = formFiles[to + 1].position;
                }
            }
            let newPosition = (below_position + above_position) / 2;

            // sending modification to server
            API.playlists
                .changeOrder(playlistId, { file_id: formFiles[from].id, position: newPosition })
                .then((res) => {
                    if (res.status === 200) {
                        resolve(true);
                    } else {
                        setNotification(true, `Error when changing order (${res.status})`);
                        resolve(false);
                    }
                })
                .catch((err) => {
                    setNotification(true, err);
                    resolve(false);
                });
        });
    };

    const [timeout, setTimeout2] = useState();
    const [originSecs, setOriginSecs] = useState();
    const handleChangeSeconds = (seconds, index) => {
        if (!originSecs) setOriginSecs(form.values.files[index].seconds);
        changeSecsForm(seconds, index);
        if (timeout) clearTimeout(timeout);
        setTimeout2(setTimeout(() => changeSeconds(seconds, index), 1000));
    };

    const changeSecsForm = (seconds, index) => {
        form.setFieldValue(
            form.values.files.map((file, i) => {
                if (index === i) {
                    file.seconds = seconds;
                    return seconds;
                } else {
                    return file;
                }
            })
        );
    };

    const changeSeconds = (seconds, index) => {
        const fileId = form.values.files[index].id;
        API.playlists
            .changeSeconds(playlistId, { file_id: fileId, seconds: seconds })
            .then((res) => {
                if (res.status === 200) {
                    setOriginSecs();
                } else {
                    setNotification(true, `Error when changing seconds (${res.status})`);
                    changeSecsForm(originSecs, index);
                }
            })
            .catch((err) => {
                setNotification(true, err);
                changeSecsForm(originSecs, index);
            });
    };

    const handleDelete = (index) => {
        API.playlists
            .removeFile(playlistId, { file_id: form.values.files[index].pfid })
            .then((res) => {
                if (res.status === 200) {
                    form.removeListItem('files', index);
                } else {
                    setNotification(true, `Error when changing order (${res.status})`);
                }
            })
            .catch((err) => {
                setNotification(true, err);
            });
    };

    const fields = form.values.files.map((_, index) => (
        <Draggable key={index} index={index} draggableId={index.toString()}>
            {(provided) => (
                <Group ref={provided.innerRef} mt="xs" {...provided.draggableProps} position="center">
                    <Paper p="xs" radius="sm" shadow="sm" withBorder spacing="xs" style={{ width: '90%' }}>
                        <Flex direction="row" align="center" gap="lg" justify="flex-end">
                            <Text>{form.getInputProps(`files.${index}.name`).value}</Text>
                            <Image width={150} src={'/api/file/' + form.getInputProps(`files.${index}.id`).value} />
                            { canEdit ? 
                            <NumberInput
                                required
                                hideControls
                                description="Seconds to display"
                                value={form.getInputProps(`files.${index}.seconds`).value}
                                onChange={(secs) => handleChangeSeconds(secs, index)}
                                error={form.getInputProps(`files.${index}.seconds`).errors && 'This field is required'}
                            />
                            : <Text>Display time: {parseTime(form.getInputProps(`files.${index}.seconds`).value)}</Text>
                            }
                            {canEdit ? (
                                <ActionIcon color="red" variant="light" size="lg" onClick={() => handleDelete(index)}>
                                    <IconTrash size="1rem" />
                                </ActionIcon>
                            ) : (
                                <></>
                            )}
                        </Flex>
                    </Paper>
                    {canEdit ? (
                        <Center {...provided.dragHandleProps}>
                            <IconGripVertical size="1.2rem" />
                        </Center>
                    ) : (
                        <></>
                    )}
                </Group>
            )}
        </Draggable>
    ));

    return (
        <Box mx="auto" maw={1200}>
            <DragDropContext
                onDragEnd={({ destination, source }) => {
                    form.reorderListItem('files', { from: source.index, to: destination.index });
                    changePositionValue(source.index, destination.index).then((success) => {
                        if (!success) {
                            form.reorderListItem('files', { from: destination.index, to: source.index });
                        }
                    });
                }}
            >
                <StrictModeDroppable droppableId="dnd-list" direction="vertical">
                    {(provided) => (
                        <div {...provided.droppableProps} ref={provided.innerRef}>
                            {fields}
                            {provided.placeholder}
                        </div>
                    )}
                </StrictModeDroppable>
            </DragDropContext>

            {canEdit ? (
                <>
                    <Group position="center" mt="md">
                        <Button vairant="light" onClick={toggleFileSelector}>
                            Select File(s)
                        </Button>
                    </Group>
                    <ModalFileSelector
                        opened={fileSelector}
                        multi
                        handleClose={toggleFileSelector}
                        handleSubmit={(files) => handleAddFiles(files)}
                    />
                </>
            ) : (
                <></>
            )}
        </Box>
    );
};

export default Content;
