import { useEffect, useRef, useState } from 'preact/hooks'

import _ from 'lodash'
import { differenceInMinutes, startOfDay } from 'date-fns'

import { WEEK_DAYS_SHORT, prettyCourseName, usePersistentState } from '../../utils.jsx'
import { layoutEvents, layoutIntervals } from '../../interval-layout.js'
import { Popup } from '../Popup.jsx'
import { Icon } from '../Icon.jsx'

const TransposePopup = ({ onClose }) => {
    return (
        <Popup
            title={
                <>
                    <Icon name="info" /> Attenzione! La tabella è stata trasposta!
                </>
            }
            onClose={onClose}
        >
            <p>A grande richiesta popolare abbiamo trasposto la tabella dell'orario!</p>

            <p>
                Assicurati quindi di leggerla correttamente (dall'alto verso il basso
                invece che da sinistra verso destra).
            </p>

            <p>
                Se preferisci utilizzare la versione vecchia, puoi utilizzare il pulsante
                Trasponi <Icon name="switch_left" style="transform: rotate(-45deg)" />{' '}
                nell'origine della tabella per trasporla. Questa scelta verrà salvata nei
                cookie e verrà ricordata in futuro
            </p>
        </Popup>
    )
}

const NoCourseWarning = () => {
    return (
        <div class="warning">
            <p>Non hai ancora selezionato nessun corso.</p>
            <p>
                Clicca sui corsi nelle altre visuali per selezionarli e visualizzarli
                nell'orario
            </p>
        </div>
    )
}

const Layout = ({ layout, day, colors }) => {
    return (
        <>
            {layout.map(block => (
                <div
                    class="event-block-wrapper"
                    style={{
                        '--time-start': block.start,
                        '--time-end': block.end,
                        '--day-position': day,
                    }}
                >
                    <div class="event-block">
                        {block.events.map((event, index) => (
                            <div
                                class="event-wrapper"
                                style={{
                                    '--block-size': block.end - block.start,
                                    '--size': event.end - event.start,
                                    '--relative-start': event.start - block.start,
                                    '--index': event.index,
                                    '--of': block.layers,
                                    '--color': `var(--event-${colors[event.id]})`,
                                }}
                            >
                                <div class="event">
                                    {event.aule.map(aula => (
                                        <div>{aula.replace(/^Fib /, '')}</div>
                                    ))}
                                </div>
                            </div>
                        ))}
                    </div>
                </div>
            ))}
        </>
    )
}

const ScheduleGrid = ({
    orientation,
    setOrientation,
    weekStart,
    weekEnd,
    dayBlocksLayout,
    colors,
}) => {
    return (
        <div
            class={`grid ${orientation}`}
            style={{
                '--time-slots': weekEnd - weekStart,
            }}
        >
            <div class="transpose-button">
                <button
                    class="small"
                    onClick={() =>
                        setOrientation(
                            orientation === 'original' ? 'transposed' : 'original'
                        )
                    }
                >
                    <Icon name="switch_left" style="transform: rotate(-45deg)" />
                </button>
            </div>
            {[1, 2, 3, 4, 5].map(n => (
                <>
                    <div class="day-label" style={`--position: ${n + 1}`}>
                        {WEEK_DAYS_SHORT[n]}
                    </div>
                    <div class="day-line" style={`--position: ${n + 1}`}></div>
                </>
            ))}

            {[9, 11, 14, 16].map(n => (
                <div
                    class="time-label"
                    style={{
                        '--position': n * 2 - weekStart,
                    }}
                >
                    {n}-{n + 2}
                </div>
            ))}
            <div class="time-line" style="--position: 0"></div>
            {[9, 11, 13, 14, 16, 18].map(n => (
                <>
                    {n * 2 > weekStart && n * 2 < weekEnd && (
                        <div
                            class="time-line"
                            style={{
                                '--position': n * 2 - weekStart,
                            }}
                        ></div>
                    )}
                </>
            ))}

            {Object.entries(dayBlocksLayout).map(([day, layout]) => (
                <Layout layout={layout} day={day} colors={colors} />
            ))}
        </div>
    )
}
const ScheduleLegend = ({ courses, colors }) => {
    return (
        <div class="legend">
            {courses.map(course => (
                <>
                    <div
                        class="color"
                        style={{
                            '--color': `var(--event-${colors[course.id]})`,
                        }}
                    ></div>
                    <div class="name">{prettyCourseName(course.name)}</div>
                </>
            ))}
        </div>
    )
}
const ScheduleCard = ({
    orientation,
    setOrientation,
    weekStart,
    weekEnd,
    dayBlocksLayout,
    courses,
    colors,
}) => {
    return (
        <div class="schedule-card">
            <ScheduleGrid
                orientation={orientation}
                setOrientation={setOrientation}
                weekStart={weekStart}
                weekEnd={weekEnd}
                dayBlocksLayout={dayBlocksLayout}
                colors={colors}
            />
            <ScheduleLegend courses={courses} colors={colors} />
        </div>
    )
}

export const Schedule = ({ timetables, selection }) => {
    const [hasSeenTranspose, setHasSeenTranspose] = usePersistentState(
        'transpose_info',
        'false'
    )
    const [orientation, setOrientation] = usePersistentState('orientation', 'original')

    const colorList = ['red', 'purple', 'blue', 'yellow', 'green', 'orange', 'lightblue']

    const allEvents = timetables['tutti']
    const selectionSet = new Set(selection)
    const events = allEvents
        .filter(e => selectionSet.has(e.id))
        .map(e => ({
            ...e,
            day: e.start.getDay(),
            start: differenceInMinutes(e.start, startOfDay(e.start)),
            end: differenceInMinutes(e.end, startOfDay(e.start)),
        }))

    const weekStart = Math.min(...events.map(e => e.start), 9 * 60) / 30
    const weekEnd = Math.max(...events.map(e => e.end), 18 * 60) / 30
    const relativeEvents = events.map(e => ({
        ...e,
        start: Math.round(e.start / 30 - weekStart),
        end: Math.round(e.end / 30 - weekStart),
    }))

    const courses = _.uniqBy(events, event => event.id)
    const colors = Object.fromEntries(
        courses.map((course, index) => {
            return [course.id, colorList[index % colorList.length]]
        })
    )

    const base = {
        1: [],
        2: [],
        3: [],
        4: [],
        5: [],
    }
    const eventsByWeekday = {
        ...base,
        ..._.groupBy(relativeEvents, event => event.day),
    }

    const dayBlocksLayout = _.mapValues(eventsByWeekday, dayEvents =>
        layoutEvents(dayEvents)
    )

    return (
        <>
            {hasSeenTranspose === 'false' && (
                <TransposePopup onClose={() => setHasSeenTranspose('true')} />
            )}
            <div class="schedule-view">
                {selection.length === 0 && <NoCourseWarning />}
                <ScheduleCard
                    orientation={orientation}
                    setOrientation={setOrientation}
                    weekStart={weekStart}
                    weekEnd={weekEnd}
                    dayBlocksLayout={dayBlocksLayout}
                    courses={courses}
                    colors={colors}
                />
            </div>
        </>
    )
}
