import { computed, ObservableSet, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../ClientUtils';
import { Doc, DocListCast } from '../../fields/Doc';
import { DocData } from '../../fields/DocSymbols';
import { ScriptField } from '../../fields/ScriptField';
import { Cast, DocCast, StrCast } from '../../fields/Types';
import { TraceMobx } from '../../fields/util';
import { emptyFunction } from '../../Utils';
import { Docs } from '../documents/Documents';
import { DocUtils } from '../documents/DocUtils';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
import { Transform } from '../util/Transform';
import { CollectionTreeView } from './collections/CollectionTreeView';
import { DocumentView } from './nodes/DocumentView';
import { DefaultStyleProvider, returnEmptyDocViewList } from './StyleProvider';
import './TemplateMenu.scss';

@observer
class OtherToggle extends React.Component<{ checked: boolean; name: string; toggle: (event: React.ChangeEvent<HTMLInputElement>) => void }> {
    render() {
        return (
            <li className="chromeToggle">
                <input type="checkbox" checked={this.props.checked} onChange={event => this.props.toggle(event)} />
                {this.props.name}
            </li>
        );
    }
}

export interface TemplateMenuProps {
    docViews: DocumentView[];
}

@observer
export class TemplateMenu extends React.Component<TemplateMenuProps> {
    _addedKeys = new ObservableSet();
    _customRef = React.createRef<HTMLInputElement>();

    componentDidMount() {
        !this._addedKeys && (this._addedKeys = new ObservableSet());
        [...Array.from(Object.keys(this.props.docViews[0].Document[DocData])), ...Array.from(Object.keys(this.props.docViews[0].Document))]
            .filter(key => key.startsWith('layout_') && (
                StrCast(this.props.docViews[0].Document[key]).startsWith("<") ||
                DocCast(this.props.docViews[0].Document[key])?.isTemplateDoc
            ))
            .forEach(key => runInAction(() => this._addedKeys.add(key.replace('layout_', '')))); // prettier-ignore
    }
    @computed get scriptField() {
        const script = ScriptField.MakeScript('docs.map(d => switchView(d, this))', { this: Doc.name }, { docs: this.props.docViews.map(dv => dv.Document) as any });
        return script ? () => script : undefined;
    }

    toggleLayout = (e: React.ChangeEvent<HTMLInputElement>, layout: string): void => {
        this.props.docViews.map(dv => dv.switchViews(e.target.checked, layout, undefined, true));
    };
    toggleDefault = (): void => {
        this.props.docViews.map(dv => dv.switchViews(false, 'layout'));
    };

    // todo: add brushes to brushMap to save with a style name
    onCustomKeypress = (e: React.KeyboardEvent) => {
        if (e.key === 'Enter') {
            runInAction(() => this._addedKeys.add(this._customRef.current!.value));
        }
    };

    return100 = () => 300;
    templateIsUsed = (selDoc: Doc, templateDoc: Doc) => {
        const template = StrCast(templateDoc.dragFactory ? Cast(templateDoc.dragFactory, Doc, null)?.title : templateDoc.title);
        return StrCast(selDoc.layout_fieldKey) === 'layout_' + template ? 'check' : 'unchecked';
    };
    render() {
        TraceMobx();
        const firstDoc = this.props.docViews[0].Document;
        const templateName = StrCast(firstDoc.layout_fieldKey, 'layout').replace('layout_', '');
        const noteTypes = DocListCast(Cast(Doc.UserDoc().template_notes, Doc, null)?.data);
        const addedTypes = DocListCast(Cast(Doc.UserDoc().template_clickFuncs, Doc, null)?.data);
        const templateMenu: Array<JSX.Element> = [];
        templateMenu.push(<OtherToggle key="default" name={firstDoc.layout instanceof Doc ? StrCast(firstDoc.layout.title) : 'Default'} checked={templateName === 'layout'} toggle={this.toggleDefault} />);
        // eslint-disable-next-line no-return-assign
        addedTypes.concat(noteTypes).map(template => (template.treeView_Checked = this.templateIsUsed(firstDoc, template)));
        this._addedKeys &&
            Array.from(this._addedKeys)
                .filter(key => !noteTypes.some(nt => nt.title === key))
                .forEach(template => templateMenu.push(<OtherToggle key={template} name={template} checked={templateName === template} toggle={e => this.toggleLayout(e, template)} />));
        return (
            <ul className="template-list">
                {Doc.noviceMode ? null : <input placeholder="+ layout" ref={this._customRef} onKeyDown={this.onCustomKeypress} />}
                {templateMenu}
                <CollectionTreeView
                    Document={Doc.MyTemplates}
                    docViewPath={returnEmptyDocViewList}
                    styleProvider={DefaultStyleProvider}
                    childFilters={returnEmptyFilter}
                    childFiltersByRanges={returnEmptyFilter}
                    searchFilterDocs={returnEmptyDoclist}
                    onCheckedClick={this.scriptField}
                    onChildClick={this.scriptField}
                    isAnyChildContentActive={returnFalse}
                    isContentActive={returnTrue}
                    focus={emptyFunction}
                    whenChildContentsActiveChanged={emptyFunction}
                    ScreenToLocalTransform={Transform.Identity}
                    isSelected={returnFalse}
                    pinToPres={emptyFunction}
                    select={emptyFunction}
                    renderDepth={1}
                    addDocTab={returnFalse}
                    PanelWidth={this.return100}
                    PanelHeight={this.return100}
                    treeViewHideHeaderFields
                    treeViewHideTitle
                    dontRegisterView
                    fieldKey="data"
                    moveDocument={returnFalse}
                    removeDocument={returnFalse}
                    addDocument={returnFalse}
                />
            </ul>
        );
    }
}

// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function switchView(doc: Doc, templateIn: Doc | undefined) {
    const template = templateIn?.dragFactory ? Cast(templateIn.dragFactory, Doc, null) : templateIn;
    const templateTitle = StrCast(template?.title);
    return templateTitle && DocUtils.makeCustomViewClicked(doc, Docs.Create.FreeformDocument, templateTitle, template);
});
