import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, makeAutoObservable, makeObservable, observable, reaction, runInAction } from "mobx";
import React from "react";
import { returnFalse, returnEmptyFilter, returnTrue } from "../../../../../../ClientUtils";
import { emptyFunction } from "../../../../../../Utils";
import { Doc, 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 { TemplateMenuAIUtils } from "../Backend/TemplateMenuAIUtils";
import { ObservableReactComponent } from "../../../../ObservableReactComponent";
import { IDisposer } from "mobx-utils";
import { ImageField } from "../../../../../../fields/URLField";
import { DocCreatorMenuButton } from "./DocCreatorMenuButton";
import { TbHistory } from "react-icons/tb";
import { IconProp } from "@fortawesome/fontawesome-svg-core";
import { docStyle } from "pdfjs-dist/types/web/ui_utils";

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.';

    @observable private promptInput: HTMLTextAreaElement | null = null;

    @observable _loading: boolean = false;
    @observable _variationsTabOpen: boolean = false;
    @observable _variationURLs: string[] = [];

    @observable private fireflyOptions: FireflyStructureOptions = {numVariations: 3, temperature: 0, useStyleRef: false};

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

    generateVariations = async () => {
        this._props.menu._variations = [];
        this._loading = true;
        const cloneTemplate = this._props.template.clone(false);
        cloneTemplate.setMatteBackground();
        const doc: Doc = cloneTemplate.getRenderedDoc()!;
        this._variationURLs = await this._props.menu.generateVariations(doc, this.prompt, this.fireflyOptions);
        this._variationURLs.forEach(url => {
            const newTemplate: Template = this._props.template.clone(true);
            this._props.menu._variations.push(newTemplate);
        });
        setTimeout(() => {
            this._variationURLs.forEach((url, i) => {
                this._props.menu._variations[i].setImageAsBackground(url, true);
            });
            this._loading = false;
        });
    }

    setPromptInputRef: React.LegacyRef<HTMLTextAreaElement> = (node) => {
        this.promptInput = node;
    }

    private optionsButtonOpts: [IconProp, () => any] = ['gear', () => {}];
    private previewBoxRightButtonOpts: [IconProp, () => any] = ['gear', () => this.forceUpdate()];

    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={this.setPromptInputRef}
                            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={(e) => runInAction(() => 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={(e) => runInAction(() => 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={(e) => runInAction(() => 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?.());
    }

    setContainerRef: React.LegacyRef<HTMLDivElement> = (node) => {
        this.previewWindow = node;
    }

    @action setVariationTab = (open: boolean) => {
        this._variationsTabOpen = open;
        if (this.previewWindow && open) {
            this.previewWindow.style.height = String(Number(this.previewWindow.clientHeight) * .6);
        } else if (this.previewWindow && !open) {
            this.previewWindow.style.height = String(Number(this.previewWindow.clientHeight) * 5/3);
        }
    }
   
    get renderedDocPreview(){
        const doc: Doc = this._props.template.getRenderedDoc() as unknown as Doc;

        return (
            <div className="docCreatorMenu-expanded-template-preview" ref={this.setContainerRef}>
                {this.previewWindow ? <DocumentView
                    Document={doc}
                    isContentActive={emptyFunction}
                    addDocument={returnFalse}
                    moveDocument={returnFalse}
                    removeDocument={returnFalse}
                    PanelWidth={() => this.previewWindow?.clientWidth ?? 500}
                    PanelHeight={() => this.previewWindow?.clientHeight ?? 500}
                    ScreenToLocalTransform={() => new Transform(-this._props.menu._pageX - 5, -this._props.menu._pageY - 35, 1)}
                    renderDepth={5}
                    whenChildContentsActiveChanged={emptyFunction}
                    focus={emptyFunction}
                    styleProvider={DefaultStyleProvider}
                    addDocTab={DocumentViewInternal.addDocTabFunc}
                    pinToPres={() => undefined}
                    childFilters={returnEmptyFilter}
                    childFiltersByRanges={returnEmptyFilter}
                    searchFilterDocs={returnEmptyDoclist}
                    fitContentsToBox={returnFalse}
                    fitWidth={returnFalse}
                /> : null}
            </div>
        )
    }

    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={() => {
                                if (this._props.template === this._props.menu._selectedTemplate) {
                                    this._props.menu.updateRenderedPreviewCollection(this._props.template);
                                }
                                this._props.menu.setExpandedView(undefined);
                            }}/>
                        <DocCreatorMenuButton icon={'lightbulb'} function={() => this.setVariationTab(!this._variationsTabOpen)}/>
                        <DocCreatorMenuButton icon={'arrow-rotate-backward'} function={() => { this._props.menu.editLastTemplate(); this.forceUpdate(); }}/>
                    </div>
                </div>
            </div>
        );
    }
}