import _ from 'lodash'
import { render } from 'preact'
import { useEffect, useState } from 'preact/hooks'
import { ToolOverlay } from './components/CourseVisibility.jsx'

import { EventsView, MODE_WORKWEEK_GRID } from './components/EventsView.jsx'
import { HamburgerMenu } from './components/HamburgerMenu.jsx'
import { Help } from './components/Help.jsx'
import { Icon } from './components/Icon.jsx'
import { Popup } from './components/Popup.jsx'
import { Toolbar } from './components/Toolbar.jsx'

window._ = _
window.dataBuffer = {}

const CALENDAR_IDS = {
    'anno-1': ['6308cfcb1df5cb026699ce32'],
    'anno-2': ['6308e2dc09352a0208fefdd9'],
    'anno-3': ['6308e42a1df5cb026699ced4'],
    'magistrale': ['6308e8ea0c34e703bb1f7e85'],
    'tutti': [
        '6308cfcb1df5cb026699ce32',
        '6308e2dc09352a0208fefdd9',
        '6308e42a1df5cb026699ced4',
        '6308e8ea0c34e703bb1f7e85',
    ],
}

async function loadEventi(ids) {
    const calendari = await Promise.all(
        ids.map(async id => {
            // Almost directly copy-pasted from Chrome Dev Tools
            const req = await fetch(
                'https://apache.prod.up.cineca.it/api/Impegni/getImpegniCalendarioPubblico',
                {
                    headers: {
                        'content-type': 'application/json;charset=UTF-8',
                        'sec-fetch-dest': 'empty',
                        'sec-fetch-mode': 'cors',
                        'sec-fetch-site': 'same-site',
                    },
                    body: JSON.stringify({
                        mostraImpegniAnnullati: true,
                        mostraIndisponibilitaTotali: false,
                        linkCalendarioId: id,
                        clienteId: '628de8b9b63679f193b87046',
                        pianificazioneTemplate: false,
                        dataInizio: '2022-10-02T22:00:00.000Z',
                        dataFine: '2022-10-07T22:00:00.000Z',
                    }),
                    method: 'POST',
                    mode: 'cors',
                    credentials: 'omit',
                }
            )

            return await req.json()
        })
    )

    // console.log(calendari)

    if (ids.length === 1) {
        return calendari[0]
    }

    return _.uniqBy(_.concat(...calendari), 'id')
}

const App = ({}) => {
    // Data Sources
    const [source, setSource] = useState('anno-1')
    const [eventi, setEventi] = useState([])

    // View Modes
    const [mode, setMode] = useState(MODE_WORKWEEK_GRID)

    // Selection
    const [selectedCourses, setSelectedCourses] = useState([])
    const [hideOtherCourses, setHideOtherCourses] = useState(false)

    // Menus
    const [helpVisible, setHelpVisible] = useState(false)
    const [showMobileMenu, setShowMobileMenu] = useState(false)

    useEffect(async () => {
        console.log('source changed')
        const eventi = await loadEventi(CALENDAR_IDS[source])

        window.dataBuffer[source] = eventi

        setEventi(eventi)
    }, [source])

    const groupIds = new Set(eventi.map(e => e.nome))
    const toolOverlayVisible =
        selectedCourses.length > 0 && selectedCourses.filter(id => groupIds.has(id)).length > 0

    useEffect(() => {
        console.log('course length changed')
        const groupIds = new Set(eventi.map(e => e.nome))

        if (
            selectedCourses.length === 0 ||
            selectedCourses.filter(id => groupIds.has(id)).length === 0
        ) {
            setHideOtherCourses(false)
        }
    }, [eventi, selectedCourses.length])

    const [theme, setTheme] = useState(
        localStorage.getItem('theme') ??
            (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
    )

    document.body.classList.toggle('dark-mode', theme === 'dark')
    localStorage.setItem('theme', theme)

    return (
        <>
            <Toolbar
                {...{
                    mode,
                    setMode,
                    source,
                    setSource,
                    onShowMenu: () => setShowMobileMenu(true),
                    onHelp: () => setHelpVisible(true),
                    theme,
                    setTheme,
                }}
            />
            <EventsView
                mode={mode}
                selection={selectedCourses}
                setSelection={setSelectedCourses}
                hideOtherCourses={hideOtherCourses}
                start={new Date(2022, 10, 3)}
                events={eventi.map(({ nome, dataInizio, dataFine, docenti, aule }) => ({
                    id: nome,
                    name: _.split(nome, '-', 1)[0].trim(),
                    start: new Date(dataInizio),
                    end: new Date(dataFine),
                    docenti: docenti.map(({ nome, cognome }) =>
                        _.startCase(_.lowerCase(nome) + ' ' + _.lowerCase(cognome))
                    ),
                    aula: _.startCase(aule[0].codice.toLowerCase()).replace(
                        /([A-Z]) ([1-9])/,
                        '$1$2'
                    ),
                }))}
            />
            {toolOverlayVisible && (
                <ToolOverlay
                    visibility={hideOtherCourses}
                    toggleVisibility={() => setHideOtherCourses(s => !s)}
                    onClose={() => {
                        setSelectedCourses([])
                        setHideOtherCourses(false)
                    }}
                />
            )}
            {showMobileMenu && (
                <HamburgerMenu
                    {...{
                        mode,
                        setMode,
                        source,
                        setSource,
                        theme,
                        setTheme,
                        onClose: () => {
                            setShowMobileMenu(false)
                        },
                    }}
                />
            )}
            {helpVisible && (
                <Popup
                    title={
                        <>
                            <Icon name="info" /> Guida
                        </>
                    }
                    onClose={() => setHelpVisible(false)}
                >
                    <Help />
                </Popup>
            )}
        </>
    )
}

render(<App />, document.body)
