import React, { useEffect, useState } from 'react';
import { Box, Typography, IconButton, Button, CircularProgress } from '@material-ui/core';
import AudiotrackIcon from '@material-ui/icons/Audiotrack';
import PersonIcon from '@material-ui/icons/Person';
import AlbumIcon from '@material-ui/icons/Album';
import * as serverApi from '../../api';
import { WindowState } from './Windows';
import { ArtistMetadata } from './ArtistWindow';
import { AlbumMetadata } from './AlbumWindow';
import StoreLinkIcon, { whichStore } from '../common/StoreLinkIcon';
import EditableText from '../common/EditableText';
import SubmitChangesButton from '../common/SubmitChangesButton';
import { saveSongChanges } from '../../lib/saveChanges';

export type SongMetadata = serverApi.SongDetails;
export type SongMetadataChanges = serverApi.ModifySongRequest;

export interface SongWindowState extends WindowState {
    songId: number,
    metadata: SongMetadata | null,
    pendingChanges: SongMetadataChanges | null,
}

export enum SongWindowStateActions {
    SetMetadata = "SetMetadata",
    SetPendingChanges = "SetPendingChanges",
    Reload = "Reload",
}

export function SongWindowReducer(state: SongWindowState, action: any) {
    switch (action.type) {
        case SongWindowStateActions.SetMetadata:
            return { ...state, metadata: action.value }
        case SongWindowStateActions.SetPendingChanges:
            return { ...state, pendingChanges: action.value }
        case SongWindowStateActions.Reload:
            return { ...state, metadata: null, pendingChanges: null }
        default:
            throw new Error("Unimplemented SongWindow state update.")
    }
}

export interface IProps {
    state: SongWindowState,
    dispatch: (action: any) => void,
    mainDispatch: (action: any) => void,
}

export async function getSongMetadata(id: number) {
    const query = {
        prop: serverApi.QueryElemProperty.songId,
        propOperand: id,
        propOperator: serverApi.QueryFilterOp.Eq,
    };

    var q: serverApi.QueryRequest = {
        query: query,
        offsetsLimits: {
            songOffset: 0,
            songLimit: 1,
        },
        ordering: {
            orderBy: {
                type: serverApi.OrderByType.Name,
            },
            ascending: true,
        },
    };

    const requestOpts = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(q),
    };

    return (async () => {
        const response = await fetch((process.env.REACT_APP_BACKEND || "") + serverApi.QueryEndpoint, requestOpts)
        let json: any = await response.json();
        let song = json.songs[0];
        return song;
    })();
}

export default function SongWindow(props: IProps) {
    let metadata = props.state.metadata;
    let pendingChanges = props.state.pendingChanges;

    useEffect(() => {
        getSongMetadata(props.state.songId)
            .then((m: SongMetadata) => {
                props.dispatch({
                    type: SongWindowStateActions.SetMetadata,
                    value: m
                });
            })
    }, [metadata?.title]);

    const [editingTitle, setEditingTitle] = useState<string | null>(null);
    const title = <Typography variant="h4"><EditableText
        defaultValue={metadata?.title || "(Unknown title)"}
        changedValue={pendingChanges?.title || null}
        editingValue={editingTitle}
        editingLabel="Title"
        onChangeEditingValue={(v: string | null) => setEditingTitle(v)}
        onChangeChangedValue={(v: string | null) => {
            let newVal: any = { ...pendingChanges };
            if (v) { newVal.title = v }
            else { delete newVal.title }
            props.dispatch({
                type: SongWindowStateActions.SetPendingChanges,
                value: newVal,
            })
        }}
    /></Typography>

    const artists = metadata?.artists && metadata?.artists.map((artist: ArtistMetadata) => {
        return <Typography>
            {artist.name}
        </Typography>
    });

    const albums = metadata?.albums && metadata?.albums.map((album: AlbumMetadata) => {
        return <Typography>
            {album.name}
        </Typography>
    });

    const storeLinks = metadata?.storeLinks && metadata?.storeLinks.map((link: string) => {
        const store = whichStore(link);
        return store && <a
            href={link} target="_blank"
        >
            <IconButton><StoreLinkIcon
                whichStore={store}
                style={{ height: '40px', width: '40px' }}
            />
            </IconButton>
        </a>
    });

    const [applying, setApplying] = useState(false);
    const maybeSubmitButton = pendingChanges && Object.keys(pendingChanges).length > 0 &&
        <Box>
            <SubmitChangesButton onClick={() => {
                setApplying(true);
                saveSongChanges(props.state.songId, pendingChanges || {})
                    .then(() => {
                        setApplying(false);
                        props.dispatch({
                            type: SongWindowStateActions.Reload
                        })
                    })
            }} />
            {applying && <CircularProgress />}
        </Box>

    return <Box width="100%" justifyContent="center" display="flex" flexWrap="wrap">
        <Box
            m={1}
            mt={4}
            width="80%"
        >
            <AudiotrackIcon style={{ fontSize: 80 }} />
        </Box>
        <Box
            m={1}
            width="80%"
        >
            {metadata && <Box>
                <Box m={2}>
                    {title}
                </Box>
                <Box m={0.5}>
                    <Box display="flex" alignItems="center" m={0.5}>
                        <PersonIcon />
                        <Box m={0.5}>
                            {artists}
                        </Box>
                    </Box>
                </Box>
                <Box m={0.5}>
                    <Box display="flex" alignItems="center" m={0.5}>
                        <AlbumIcon />
                        <Box m={0.5}>
                            {albums}
                        </Box>
                    </Box>
                </Box>
                <Box m={1}>
                    <Box display="flex" alignItems="center" m={0.5}>
                        {storeLinks}
                    </Box>
                </Box>
            </Box>}
        </Box>
        <Box
            m={1}
            width="80%"
        >
            {maybeSubmitButton}
        </Box>
    </Box>
}