import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import React from 'react';
import { SettingsManager } from '../../../util/SettingsManager';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { Button, IconButton, Size } from 'browndash-components';
import ReactLoading from 'react-loading';
import { AiOutlineSend } from 'react-icons/ai';
import './ImageLabelHandler.scss';
import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT';
import { InkData } from '../../../../fields/InkField';
import { SVGToBezier } from '../../../util/bezierFit';
const { parse } = require('svgson');
import { Slider, Switch } from '@mui/material';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { Flex } from '@adobe/react-spectrum';
import { Row } from 'react-aria-components';
import { UndoManager } from '../../../util/UndoManager';
import e from 'cors';

@observer
export class SmartDrawHandler extends ObservableReactComponent<{}> {
    static Instance: SmartDrawHandler;

    @observable private _display: boolean = false;
    @observable private _pageX: number = 0;
    @observable private _pageY: number = 0;
    @observable private _yRelativeToTop: boolean = true;
    @observable private _isLoading: boolean = false;
    @observable private _userInput: string = '';
    @observable private _showOptions: boolean = false;
    @observable private _menuIcon: string = 'caret-right';
    @observable private _complexity: number = 5;
    @observable private _size: number = 300;
    @observable private _autoColor: boolean = true;
    @observable private _showRegenerate: boolean = false;
    private _addToDocFunc: (strokeList: [InkData, string, string][]) => void = () => {};
    private _lastX: number = 0;
    private _lastY: number = 0;

    constructor(props: any) {
        super(props);
        makeObservable(this);
        SmartDrawHandler.Instance = this;
    }

    @action
    setUserInput = (input: string) => {
        this._userInput = input;
    };

    @action
    displaySmartDrawHandler = (x: number, y: number, addToDoc: (strokeData: [InkData, string, string][]) => void) => {
        this._pageX = x;
        this._pageY = y;
        this._display = true;
        this._addToDocFunc = addToDoc;
    };

    hideSmartDrawHandler = () => {
        this._showRegenerate = false;
        this._display = false;
        this._isLoading = false;
        this._showOptions = false;
        this._menuIcon = 'caret-right';
    };

    hideRegenerate = () => {
        this._showRegenerate = false;
        this._userInput = '';
        this._complexity = 5;
        this._size = 300;
        this._autoColor = true;
        this._isLoading = false;
    };

    toggleMenu = () => {
        this._showOptions = !this._showOptions;
        this._menuIcon === 'caret-right' ? (this._menuIcon = 'caret-down') : (this._menuIcon = 'caret-right');
    };

    @action
    drawWithGPT = async (e: React.MouseEvent<Element, MouseEvent>, startPoint: { X: number; Y: number }, input: string, regenerate: boolean = false) => {
        if (this._userInput === '') return;
        e.stopPropagation();
        this._lastX = startPoint.X;
        this._lastY = startPoint.Y;
        this._isLoading = true;
        this._showOptions = false;
        try {
            const res = await gptAPICall(`"${input}", "${this._complexity}", "${this._size}"`, GPTCallType.DRAW);
            if (!res) {
                console.error('GPT call failed');
                return;
            }
            const svg = res.match(/<svg[^>]*>([\s\S]*?)<\/svg>/g);
            if (svg) {
                const svgObject = await parse(svg[0]);
                const svgStrokes: any = svgObject.children;
                const strokeData: [InkData, string, string][] = [];
                svgStrokes.forEach((child: any) => {
                    const convertedBezier: InkData = SVGToBezier(child.name, child.attributes);
                    strokeData.push([
                        convertedBezier.map(point => {
                            return { X: point.X + startPoint.X - this._size / 1.5, Y: point.Y + startPoint.Y - this._size / 2 };
                        }),
                        this._autoColor ? child.attributes.stroke : undefined,
                        this._autoColor ? child.attributes.fill : undefined,
                    ]);
                });
                if (regenerate) UndoManager.Undo();
                this._addToDocFunc(strokeData);
            }
        } catch (err) {
            console.error('GPT call failed', err);
        }
        this.hideSmartDrawHandler();
        this._showRegenerate = true;
    };

    regenerate = (e: React.MouseEvent<Element, MouseEvent>) => {
        this.drawWithGPT(e, { X: this._lastX, Y: this._lastY }, `Regenerate the item "${this._userInput}"`, true);
    };

    render() {
        if (this._display) {
            return (
                <div
                    id="label-handler"
                    className="contextMenu-cont"
                    style={{
                        display: this._display ? '' : 'none',
                        left: this._pageX,
                        ...(this._yRelativeToTop ? { top: Math.max(0, this._pageY) } : { bottom: this._pageY }),
                        background: SettingsManager.userBackgroundColor,
                        color: SettingsManager.userColor,
                    }}>
                    <div>
                        <IconButton
                            tooltip={'Cancel'}
                            onClick={() => {
                                this.hideSmartDrawHandler();
                                this.hideRegenerate();
                            }}
                            icon={<FontAwesomeIcon icon="xmark" />}
                            color={SettingsManager.userColor}
                            style={{ width: '19px' }}
                        />
                        <input
                            aria-label="label-input"
                            id="new-label"
                            type="text"
                            style={{ color: 'black' }}
                            value={this._userInput}
                            onChange={e => {
                                this.setUserInput(e.target.value);
                            }}
                            placeholder="Enter item to draw"
                        />
                        <IconButton
                            tooltip="Advanced Options"
                            icon={<FontAwesomeIcon icon={this._showOptions ? 'caret-down' : 'caret-right'} />}
                            color={SettingsManager.userColor}
                            style={{ width: '14px' }}
                            onClick={() => {
                                this._showOptions = !this._showOptions;
                            }}
                        />
                        <Button
                            style={{ alignSelf: 'flex-end' }}
                            text="Send"
                            icon={this._isLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
                            iconPlacement="right"
                            color={SettingsManager.userColor}
                            onClick={e => {
                                this.drawWithGPT(e, { X: e.clientX, Y: e.clientY }, this._userInput);
                            }}
                        />
                    </div>
                    {this._showOptions && (
                        <>
                            <div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-around' }}>
                                <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', width: '30%' }}>
                                    Auto color
                                    <Switch
                                        sx={{
                                            '& .MuiSwitch-switchBase.Mui-checked': {
                                                color: SettingsManager.userColor,
                                            },
                                            '& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': {
                                                backgroundColor: SettingsManager.userVariantColor,
                                            },
                                        }}
                                        defaultChecked={true}
                                        size="small"
                                        onChange={() => (this._autoColor = !this._autoColor)}
                                    />
                                </div>
                                <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', width: '31%' }}>
                                    Complexity
                                    <Slider
                                        sx={{
                                            '& .MuiSlider-thumb': {
                                                color: SettingsManager.userColor,
                                                '&.Mui-focusVisible, &:hover, &.Mui-active': {
                                                    boxShadow: `0px 0px 0px 8px${SettingsManager.userColor.slice(0, 7)}10`,
                                                },
                                            },
                                            '& .MuiSlider-track': {
                                                color: SettingsManager.userVariantColor,
                                            },
                                            '& .MuiSlider-rail': {
                                                color: SettingsManager.userColor,
                                            },
                                        }}
                                        style={{ width: '80%' }}
                                        min={1}
                                        max={10}
                                        step={1}
                                        size="small"
                                        value={this._complexity}
                                        onChange={(e, val) => {
                                            this._complexity = val as number;
                                        }}
                                        valueLabelDisplay="auto"
                                    />
                                </div>
                                <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', width: '39%' }}>
                                    Size (in pixels)
                                    <Slider
                                        sx={{
                                            '& .MuiSlider-thumb': {
                                                color: SettingsManager.userColor,
                                                '&.Mui-focusVisible, &:hover, &.Mui-active': {
                                                    boxShadow: `0px 0px 0px 8px${SettingsManager.userColor.slice(0, 7)}20`,
                                                },
                                            },
                                            '& .MuiSlider-track': {
                                                color: SettingsManager.userVariantColor,
                                            },
                                            '& .MuiSlider-rail': {
                                                color: SettingsManager.userColor,
                                            },
                                        }}
                                        style={{ width: '80%' }}
                                        min={50}
                                        max={700}
                                        step={10}
                                        size="small"
                                        value={this._size}
                                        onChange={(e, val) => {
                                            this._size = val as number;
                                        }}
                                        valueLabelDisplay="auto"
                                    />
                                </div>
                            </div>
                        </>
                    )}
                </div>
            );
        } else if (this._showRegenerate) {
            return (
                <div
                    id="smartdraw-options-menu"
                    className="contextMenu-cont"
                    style={{
                        left: this._pageX,
                        ...(this._yRelativeToTop ? { top: Math.max(0, this._pageY) } : { bottom: this._pageY }),
                        background: SettingsManager.userBackgroundColor,
                        color: SettingsManager.userColor,
                    }}>
                    <div
                        style={{
                            display: 'flex',
                            flexDirection: 'row',
                        }}>
                        <IconButton tooltip="Cancel" onClick={this.hideRegenerate} icon={<FontAwesomeIcon icon="xmark" />} color={SettingsManager.userColor} style={{ width: '19px' }} />
                        <IconButton
                            tooltip="Regenerate"
                            icon={this._isLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <FontAwesomeIcon icon={'rotate'} />}
                            color={SettingsManager.userColor}
                            onClick={e => {
                                this.regenerate(e);
                            }}
                        />
                    </div>
                </div>
            );
        } else {
            return <></>;
        }
    }
}
