import React, { useState, useEffect } from 'react';

import { Query, toApiQuery, QueryOrdering, TypesIncluded, QueryKeys, OrderKey } from '../types/Query';
import FilterControl from './FilterControl';
import * as serverApi from '../api';
import BrowseWindow, { Item } from './BrowseWindow';
import { FormControl, FormLabel, FormGroup, FormControlLabel, Checkbox, Select, MenuItem } from '@material-ui/core';

const _ = require('lodash');

interface ItemTypeCheckboxesProps {
    types: TypesIncluded,
    onChange: (types: TypesIncluded) => void;
}

function ItemTypeCheckboxes(props: ItemTypeCheckboxesProps) {
    const songChange = (v: any) => {
        props.onChange({
            [QueryKeys.Songs]: v.target.checked,
            [QueryKeys.Artists]: props.types[QueryKeys.Artists],
            [QueryKeys.Tags]: props.types[QueryKeys.Tags]
        });
    }
    const artistChange = (v: any) => {
        props.onChange({
            [QueryKeys.Songs]: props.types[QueryKeys.Songs],
            [QueryKeys.Artists]: v.target.checked,
            [QueryKeys.Tags]: props.types[QueryKeys.Tags]
        });
    }
    const tagChange = (v: any) => {
        props.onChange({
            [QueryKeys.Songs]: props.types[QueryKeys.Songs],
            [QueryKeys.Artists]: props.types[QueryKeys.Artists],
            [QueryKeys.Tags]: v.target.checked
        });
    }

    return <FormControl component='fieldset'>
        <FormLabel component='legend'>Result types</FormLabel>
        <FormGroup>
            <FormControlLabel
                control={<Checkbox checked={props.types[QueryKeys.Songs]} onChange={songChange} name='Songs' />}
                label="Songs"
            />
            <FormControlLabel
                control={<Checkbox checked={props.types[QueryKeys.Artists]} onChange={artistChange} name='Artists' />}
                label="Artists"
            />
            <FormControlLabel
                control={<Checkbox checked={props.types[QueryKeys.Tags]} onChange={tagChange} name='Tags' />}
                label="Tags"
            />
        </FormGroup>
    </FormControl>;
}

interface OrderingWidgetProps {
    ordering: QueryOrdering,
    onChange: (o: QueryOrdering) => void;
}

function OrderingWidget(props: OrderingWidgetProps) {
    const onTypeChange = (e: any) => {
        props.onChange({
            [QueryKeys.OrderBy]: {
                [QueryKeys.OrderKey]: e.target.value,
            },
            [QueryKeys.Ascending]: props.ordering[QueryKeys.Ascending],
        });
    }
    const onAscendingChange = (e: any) => {
        props.onChange({
            [QueryKeys.OrderBy]: props.ordering[QueryKeys.OrderBy],
            [QueryKeys.Ascending]: (e.target.value == 'asc'),
        });
    }

    return <FormControl component='fieldset'>
        <FormLabel component='legend'>Ordering</FormLabel>
        <FormGroup>
            <Select
                onChange={onTypeChange}
                value={props.ordering[QueryKeys.OrderBy][QueryKeys.OrderKey]}
            >
                <MenuItem value={OrderKey.Name}>Name</MenuItem>
            </Select>
            <Select
                onChange={onAscendingChange}
                value={props.ordering[QueryKeys.Ascending] ? 'asc' : 'desc'}
            >
                <MenuItem value={'asc'}>Ascending</MenuItem>
                <MenuItem value={'desc'}>Descending</MenuItem>
            </Select>
        </FormGroup>
    </FormControl>;
}

function toServerOrdering(o: QueryOrdering | undefined): serverApi.Ordering {
    if (!o) {
        return {
            orderBy: {
                type: serverApi.OrderByType.Name
            },
            ascending: true
        };
    }

    const keys = {
        [OrderKey.Name]: serverApi.OrderByType.Name,
    };

    return {
        orderBy: {
            type: keys[o[QueryKeys.OrderBy][QueryKeys.OrderKey]]
        },
        ascending: o[QueryKeys.Ascending],
    }
}

export interface IProps {
    query: Query | undefined,
    typesIncluded: TypesIncluded | undefined,
    resultOrder: QueryOrdering | undefined,
    onQueryChange: (q: Query) => void,
    onTypesChange: (t: TypesIncluded) => void,
    onOrderChange: (o: QueryOrdering) => void,
}

export default function QueryBrowseWindow(props: IProps) {
    const [songs, setSongs] = useState<serverApi.SongDetails[]>([]);
    const [artists, setArtists] = useState<serverApi.ArtistDetails[]>([]);
    //const [tags, setTags] = useState<serverApi.TagDetails[]>([]);

    var items: Item[] = [];
    props.typesIncluded && props.typesIncluded[QueryKeys.Songs] && items.push(...songs);
    props.typesIncluded && props.typesIncluded[QueryKeys.Artists] && items.push(...artists);

    useEffect(() => {
        if (!props.query) { return; }
        const q = _.cloneDeep(props.query);
        const r = _.cloneDeep(props.resultOrder);
        const t = _.cloneDeep(props.typesIncluded);

        const request: serverApi.QueryRequest = {
            query: toApiQuery(props.query),
            offsetsLimits: {
                songOffset: 0,
                songLimit: 5, // TODO
                artistOffset: 0,
                artistLimit: 5,
                tagOffset: 0,
                tagLimit: 5,
            },
            ordering: toServerOrdering(props.resultOrder),
        }
        const requestOpts = {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(request)
        };
        fetch(serverApi.QueryEndpoint, requestOpts)
            .then((response: any) => response.json())
            .then((json: any) => {
                const match = _.isEqual(q, props.query) && _.isEqual(r, props.resultOrder) && _.isEqual(t, props.typesIncluded);
                'songs' in json && match && setSongs(json.songs);
                'artists' in json && match && setArtists(json.artists);
            });
    }, [props.query]);

    return <>
        <FormControl component='fieldset'>
            <FormLabel component='legend'>Query</FormLabel>
            <FilterControl
                query={props.query}
                onChangeQuery={props.onQueryChange}
            />
        </FormControl>
        <ItemTypeCheckboxes
            types={props.typesIncluded || {
                [QueryKeys.Songs]: true,
                [QueryKeys.Artists]: true,
                [QueryKeys.Tags]: true,
            }}
            onChange={props.onTypesChange}
        />
        <OrderingWidget
            ordering={props.resultOrder || {
                [QueryKeys.OrderBy]: {
                    [QueryKeys.OrderKey]: OrderKey.Name
                },
                [QueryKeys.Ascending]: true
            }}
            onChange={props.onOrderChange}
        />
        <BrowseWindow items={items} />
    </>
}
