import { action, makeObservable, observable, reaction } from 'mobx';
import React from 'react';
import { returnFalse, returnEmptyFilter } from '../../../../../../ClientUtils';
import { emptyFunction } from '../../../../../../Utils';
import { returnEmptyDoclist } from '../../../../../../fields/Doc';
import { DefaultStyleProvider } from '../../../../StyleProvider';
import { DocumentView, DocumentViewInternal } from '../../../DocumentView';
import { DocCreatorMenu } from '../DocCreatorMenu';
import { TemplatePreviewGrid } from './TemplatePreviewGrid';
import { observer } from 'mobx-react';
import { Transform } from '../../../../../util/Transform';
import { Template } from '../Template';
import { ObservableReactComponent } from '../../../../ObservableReactComponent';
import { IDisposer } from 'mobx-utils';
import { DocCreatorMenuButton } from './DocCreatorMenuButton';
import { IconProp } from '@fortawesome/fontawesome-svg-core';

export type FireflyStructureOptions = {
    numVariations: number;
    temperature: number;
    useStyleRef: boolean;
};

interface FireflyVariationsTabProps {
    menu: DocCreatorMenu;
    template: Template;
}

@observer
export class FireflyVariationsTab extends ObservableReactComponent<FireflyVariationsTabProps> {
    private _prompt: string = 'Use this template to generate an empty baseball card template.';
    private _optionsButtonOpts: [IconProp, () => void] = ['gear', emptyFunction];
    private _previewBoxRightButtonOpts: [IconProp, () => void] = ['gear', () => this.forceUpdate()];

    @observable _fireflyOptions: FireflyStructureOptions = { numVariations: 3, temperature: 0, useStyleRef: false };
    @observable _promptInput: HTMLTextAreaElement | null = null;
    @observable _loading: boolean = false;
    @observable _variationsTabOpen: boolean = false;
    @observable _variationURLs: string[] = [];

    constructor(props: FireflyVariationsTabProps) {
        super(props);
        makeObservable(this);
    }

    generateVariations = action(async () => {
        this._props.menu._variations = [];
        this._loading = true;
        const cloneTemplate = this._props.template.clone(false);
        cloneTemplate.setMatteBackground();
        const doc = cloneTemplate.getRenderedDoc()!;
        this._props.menu.generateVariations(doc, this._prompt, this._fireflyOptions).then(
            action((urls: string[]) => {
                (this._variationURLs = urls).forEach(url => {
                    const template = this._props.template.clone(true);
                    template.setImageAsBackground(url, true);
                    this._props.menu._variations.push(template);
                });
                this._loading = false;
            })
        );
    });

    render() {
        return (
            <div className="docCreatorMenu-editing-firefly-section">
                <div className="docCreatorMenu-option-divider full no-margin-bottom" />
                <TemplatePreviewGrid
                    menu={this._props.menu}
                    title="Generate Variations"
                    loading={this._loading}
                    styles="scrolling"
                    templates={this._props.menu._variations}
                    optionsButtonOpts={this._optionsButtonOpts}
                    previewBoxRightButtonOpts={this._previewBoxRightButtonOpts}
                />
                <div className="docCreatorMenu-firefly-options">
                    <div className="docCreatorMenu-variation-prompt-row">
                        <textarea
                            className="docCreatorMenu-variation-prompt-input-textbox"
                            ref={action((node: HTMLTextAreaElement | null) => (this._promptInput = node))}
                            onChange={e => (this._prompt = e.target.value)}
                            onInput={() => {
                                if (this._promptInput !== null) {
                                    this._promptInput.style.height = 'auto';
                                    this._promptInput.style.height = this._promptInput.scrollHeight + 'px';
                                }
                            }}
                            defaultValue=""
                            placeholder="Enter a custom prompt here (optional)"
                        />
                        <DocCreatorMenuButton icon={'arrows-rotate'} styles={'border'} function={this.generateVariations} />
                    </div>
                    <nav className="options‑menu">
                        <label className="menu‑item switch">
                            <input type="checkbox" checked={this._fireflyOptions.useStyleRef} onChange={action(e => (this._fireflyOptions.useStyleRef = e.target.checked))} />
                            <span className="slider round"></span>
                            <span className="firefly-option-label">Use template as style guide</span>
                        </label>
                        <div className="menu‑item">
                            <span className="firefly-option-label">Variations</span>
                            <input type="range" id="variations" min="1" max="5" value={this._fireflyOptions.numVariations} onChange={action(e => (this._fireflyOptions.numVariations = Number(e.target.value)))} />
                            <span className="value" id="varVal">
                                {this._fireflyOptions.numVariations}
                            </span>
                        </div>
                        <div className="menu‑item">
                            <span className="firefly-option-label">Temperature</span>
                            <input type="range" id="temperature" min="1" max="100" value={this._fireflyOptions.temperature} onChange={action(e => (this._fireflyOptions.temperature = Number(e.target.value)))} />
                            <span className="value" id="tempVal">
                                {this._fireflyOptions.temperature}
                            </span>
                        </div>
                    </nav>
                </div>
            </div>
        );
    }
}

interface TemplateEditingWindowProps {
    menu: DocCreatorMenu;
    template: Template;
}

@observer
export class TemplateEditingWindow extends ObservableReactComponent<TemplateEditingWindowProps> {
    private disposers: { [name: string]: IDisposer } = {};

    @observable private _previewWindow: HTMLDivElement | null = null;
    @observable _variationsTabOpen: boolean = false;

    constructor(props: TemplateEditingWindowProps) {
        super(props);
        makeObservable(this);
    }

    componentDidMount(): void {
        this.disposers.windowDimensions = reaction(
            () => this._props.menu._resizing,
            () => this.forceUpdate(),
            { fireImmediately: true }
        );
    }

    componentWillUnmount() {
        Object.values(this.disposers).forEach(disposer => disposer?.());
    }

    @action setVariationTab = (open: boolean) => {
        this._variationsTabOpen = open;
        if (this._previewWindow && open) {
            this._previewWindow.style.height = String(Number(this._previewWindow.clientHeight) * 0.6);
        } else if (this._previewWindow && !open) {
            this._previewWindow.style.height = String((Number(this._previewWindow.clientHeight) * 5) / 3);
        }
    };

    previewPanelWidth = () => this._previewWindow?.clientWidth ?? 500;
    previewPanelHeight = () => this._previewWindow?.clientHeight ?? 500;
    previewScreenToLocalXf = () => new Transform(-this._props.menu._pageX - 5, -this._props.menu._pageY - 35, 1);
    get renderedDocPreview() {
        const doc = this._props.template.getRenderedDoc();
        return (
            <div className="docCreatorMenu-expanded-template-preview" ref={action((node: HTMLDivElement | null) => (this._previewWindow = node))}>
                {this._previewWindow && doc ? (
                    <DocumentView
                        Document={doc}
                        isContentActive={emptyFunction}
                        addDocument={returnFalse}
                        moveDocument={returnFalse}
                        removeDocument={returnFalse}
                        PanelWidth={this.previewPanelWidth}
                        PanelHeight={this.previewPanelHeight}
                        ScreenToLocalTransform={this.previewScreenToLocalXf}
                        renderDepth={5}
                        whenChildContentsActiveChanged={emptyFunction}
                        focus={emptyFunction}
                        styleProvider={DefaultStyleProvider}
                        addDocTab={DocumentViewInternal.addDocTabFunc}
                        pinToPres={emptyFunction}
                        childFilters={returnEmptyFilter}
                        childFiltersByRanges={returnEmptyFilter}
                        searchFilterDocs={returnEmptyDoclist}
                        // fitContentsToBox={returnFalse}
                        // fitWidth={returnFalse}
                    />
                ) : null}
            </div>
        );
    }

    expandFunc = () => {
        // if (this._props.template === this._props.menu._selectedTemplate) {
        //     this._props.menu.updateRenderedPreviewCollection(this._props.template);
        // }
        this._props.menu.setExpandedView(undefined);
    };
    lastFunc = () => {
        this._props.menu.editLastTemplate();
        this.forceUpdate();
    };
    variationFunc = () => this.setVariationTab(!this._variationsTabOpen);
    render() {
        return (
            <div className="docCreatorMenu-templates-view">
                <div className="docCreatorMenu-expanded-template-preview">
                    <div className="top-panel" />
                    {this.renderedDocPreview}
                    {this._variationsTabOpen ? <FireflyVariationsTab menu={this._props.menu} template={this._props.template} /> : null}
                    <div className="right-buttons-panel">
                        <DocCreatorMenuButton icon="minimize" function={this.expandFunc} />
                        <DocCreatorMenuButton icon="lightbulb" function={this.variationFunc} />
                        <DocCreatorMenuButton icon="arrow-rotate-backward" function={this.lastFunc} />
                    </div>
                </div>
            </div>
        );
    }
}
