/**
 * This creates a dropdown menu that's populated with possible field key names (e.g., author, tags)
 *
 * The set of field names actually displayed is based on searching the prop 'Document' and its descendants :
 *     The field list will contain all of the fields within the prop Document and all of its children;
 *     this list is then pruned down to only include fields that are not marked in Documents.ts to be non-filterable
 */

import { computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import Select from 'react-select';
import { Doc } from '../../fields/Doc';
import { DocOptions, FInfo } from '../documents/Documents';
import { SearchUtil } from '../util/SearchUtil';
import { SnappingManager } from '../util/SnappingManager';
import './FilterPanel.scss';
import { ObservableReactComponent } from './ObservableReactComponent';

interface fieldsDropdownProps {
    Document: Doc; // show fields for this Doc if set, otherwise for all docs in dashboard
    selectFunc: (value: string) => void;
    menuClose?: () => void;
    placeholder?: string | (() => string);
    showPlaceholder?: true; // if true, then input field always shows the placeholder value; otherwise, it shows the current selection
    addedFields?: string[];
}

@observer
export class FieldsDropdown extends ObservableReactComponent<fieldsDropdownProps> {
    @observable _newField = '';
    constructor(props: any) {
        super(props);
        makeObservable(this);
    }

    @computed get allDescendantDocs() { //!!!
        const allDocs = new Set<Doc>();
        SearchUtil.foreachRecursiveDoc([this._props.Document], (depth, doc) => allDocs.add(doc));
        return Array.from(allDocs);
    }

    @computed get fieldsOfDocuments() {
        const keys = new Set<string>();
        this.allDescendantDocs.forEach(doc => SearchUtil.documentKeys(doc).filter(key => keys.add(key)));
        const sortedKeys = Array.from(keys.keys())
            .filter(key => key[0])
            .filter(key => key.indexOf('modificationDate') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('_')) || !Doc.noviceMode)
            .sort();

        Array.from(keys).forEach(key => sortedKeys.splice(sortedKeys.indexOf(key), 1));

        return [...Array.from(keys), ...sortedKeys];
    }

    render() {
        const filteredOptions = ['author', ...(this._newField ? [this._newField] : []), ...(this._props.addedFields ?? []), ...this.fieldsOfDocuments.filter(facet => facet[0] === facet.charAt(0).toUpperCase())];

        Object.entries(DocOptions)
            .filter(opts => opts[1].filterable) //!!!
            .forEach((pair: [string, FInfo]) => filteredOptions.push(pair[0]));
        const options = filteredOptions.sort().map(facet => ({ value: facet, label: facet }));

        return (
            <Select
                styles={{
                    control: (baseStyles /* , state */) => ({
                        ...baseStyles,
                        minHeight: '5px',
                        maxHeight: '30px',
                        color: SnappingManager.userColor,
                        backgroundColor: SnappingManager.userBackgroundColor,
                        padding: 0,
                        margin: 0,
                    }),
                    singleValue: (baseStyles /* , state */) => ({
                        ...baseStyles,
                        color: SnappingManager.userColor,
                        background: SnappingManager.userBackgroundColor,
                    }),
                    placeholder: (baseStyles /* , state */) => ({
                        ...baseStyles,
                        color: SnappingManager.userColor,
                        background: SnappingManager.userBackgroundColor,
                    }),
                    input: (baseStyles /* , state */) => ({
                        ...baseStyles,
                        padding: 0,
                        margin: 0,
                        color: SnappingManager.userColor,
                        background: 'transparent',
                    }),
                    option: (baseStyles, state) => ({
                        ...baseStyles,
                        color: SnappingManager.userColor,
                        background: !state.isFocused ? SnappingManager.userBackgroundColor : SnappingManager.userVariantColor,
                    }),
                    menuList: (baseStyles /* , state */) => ({
                        ...baseStyles,
                        backgroundColor: SnappingManager.userBackgroundColor,
                    }),
                }}
                placeholder={typeof this._props.placeholder === 'string' ? this._props.placeholder : this._props.placeholder?.()}
                options={options as any}
                isMulti={false}
                onChange={val => this._props.selectFunc((val as any as { value: string; label: string }).value)}
                onKeyDown={e => {
                    if (e.key === 'Enter') {
                        runInAction(() => {
                            this._props.selectFunc((this._newField = (e.nativeEvent.target as any)?.value));
                        });
                    }
                    e.stopPropagation();
                }}
                onMenuClose={this._props.menuClose}
                closeMenuOnSelect
                value={this._props.showPlaceholder ? null : undefined}
            />
        );
    }
}
