import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { ColorState, SketchPicker } from 'react-color';
import { Doc, StrListCast } from '../../../../fields/Doc';
import { InkTool } from '../../../../fields/InkField';
import { createSchema } from '../../../../fields/Schema';
import { ScriptField } from '../../../../fields/ScriptField';
import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
import { WebField } from '../../../../fields/URLField';
import { Utils } from '../../../../Utils';
import { DocumentType } from '../../../documents/DocumentTypes';
import { ScriptingGlobals } from "../../../util/ScriptingGlobals";
import { SelectionManager } from '../../../util/SelectionManager';
import { undoBatch, UndoManager } from '../../../util/UndoManager';
import { CollectionViewType } from '../../collections/CollectionView';
import { ContextMenu } from '../../ContextMenu';
import { DocComponent } from '../../DocComponent';
import { EditableView } from '../../EditableView';
import { GestureOverlay } from '../../GestureOverlay';
import { Colors } from '../../global/globalEnums';
import { ActiveFillColor, ActiveInkColor, ActiveInkWidth, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke';
import { StyleProp } from '../../StyleProvider';
import { FieldView, FieldViewProps } from '.././FieldView';
import { RichTextMenu } from '../formattedText/RichTextMenu';
import { WebBox } from '../WebBox';
import { FontIconBadge } from './FontIconBadge';
import './FontIconBox.scss';
const FontIconSchema = createSchema({
    icon: "string",
});

export enum ButtonType {
    TextButton = "textBtn",
    MenuButton = "menuBtn",
    DropdownList = "drpdownList",
    DropdownButton = "drpdownBtn",
    ClickButton = "clickBtn",
    DoubleButton = "dblBtn",
    ToggleButton = "tglBtn",
    ColorButton = "colorBtn",
    ToolButton = "toolBtn",
    NumberButton = "numBtn",
    EditableText = "editableText"
}

export enum NumButtonType {
    Slider = "slider",
    DropdownOptions = "list",
    Inline = "inline"
}

export interface ButtonProps extends FieldViewProps {
    type?: ButtonType;
}
@observer
export class FontIconBox extends DocComponent<ButtonProps>() {
    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); }
    showTemplate = (): void => {
        const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null);
        dragFactory && this.props.addDocTab(dragFactory, "add:right");
    }
    dragAsTemplate = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); };
    useAsPrototype = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)'); };

    specificContextMenu = (): void => {
        if (!Doc.UserDoc().noviceMode) {
            const cm = ContextMenu.Instance;
            cm.addItem({ description: "Show Template", event: this.showTemplate, icon: "tag" });
            cm.addItem({ description: "Use as Render Template", event: this.dragAsTemplate, icon: "tag" });
            cm.addItem({ description: "Use as Prototype", event: this.useAsPrototype, icon: "tag" });
        }
    }

    // Determining UI Specs
    @observable private label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title));
    @observable private icon = StrCast(this.dataDoc.icon, "user") as any;
    @observable private dropdown: boolean = BoolCast(this.rootDoc.dropDownOpen);
    @observable private buttonList: string[] = StrListCast(this.rootDoc.btnList);
    @observable private type = StrCast(this.rootDoc.btnType);

    /**
     * Types of buttons in dash:
     * - Main menu button (LHS)
     * - Tool button
     * - Expandable button (CollectionLinearView)
     * - Button inside of CollectionLinearView vs. outside of CollectionLinearView
     * - Action button
     * - Dropdown button 
     * - Color button
     * - Dropdown list
     * - Number button
    **/

    _batch: UndoManager.Batch | undefined = undefined;
    /**
     * Number button
     */
    @computed get numberButton() {
        const numBtnType: string = StrCast(this.rootDoc.numBtnType);
        const numScript = ScriptCast(this.rootDoc.script);
        const setValue = (value: number) => numScript?.script.run({ value, _readOnly_: false });

        // Script for checking the outcome of the toggle
        const checkResult: number = numScript?.script.run({ value: 0, _readOnly_: true }).result || 0;

        const label = !Doc.UserDoc()._showLabel ? (null) :
            <div className="fontIconBox-label">
                {this.label}
            </div>;

        if (numBtnType === NumButtonType.Slider) {
            const dropdown = <div className="menuButton-dropdownBox" onPointerDown={e => e.stopPropagation()} >
                <input type="range" step="1" min={NumCast(this.rootDoc.numBtnMin, 0)} max={NumCast(this.rootDoc.numBtnMax, 100)} value={checkResult}
                    className={"menu-slider"} id="slider"
                    onPointerDown={() => this._batch = UndoManager.StartBatch("presDuration")}
                    onPointerUp={() => this._batch?.end()}
                    onChange={e => { e.stopPropagation(); setValue(Number(e.target.value)); }}
                />
            </div>;
            return (
                <div
                    className={`menuButton ${this.type} ${numBtnType}`}
                    onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}
                >
                    {checkResult}
                    {label}
                    {this.rootDoc.dropDownOpen ? dropdown : null}
                </div>
            );
        } else if (numBtnType === NumButtonType.DropdownOptions) {
            const items: number[] = [];
            for (let i = 0; i < 100; i++) {
                if (i % 2 === 0) {
                    items.push(i);
                }
            }
            const list = items.map((value) => {
                return <div className="list-item" key={`${value}`}
                    style={{
                        backgroundColor: value === checkResult ? Colors.LIGHT_BLUE : undefined
                    }}
                    onClick={() => setValue(value)}>
                    {value}
                </div>;
            });
            return (
                <div
                    className={`menuButton ${this.type} ${numBtnType}`}
                >
                    <div className={`button`} onClick={action((e) => setValue(Number(checkResult) - 1))}>
                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"minus"} />
                    </div>
                    <div
                        className={`button ${'number'}`}
                        onPointerDown={(e) => {
                            e.stopPropagation();
                            e.preventDefault();
                        }}
                        onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}
                    >
                        <input
                            style={{ width: 30 }}
                            className="button-input"
                            type="number"
                            value={checkResult}
                            onChange={action((e) => setValue(Number(e.target.value)))}
                        />
                    </div>
                    <div className={`button`} onClick={action((e) => setValue(Number(checkResult) + 1))}>
                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"plus"} />
                    </div>

                    {this.rootDoc.dropDownOpen ?
                        <div>
                            <div className="menuButton-dropdownList"
                                style={{ left: "25%" }}>
                                {list}
                            </div>
                            <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
                        </div> : null}

                </div>
            );
        } else {
            return (
                <div>

                </div>
            );
        }


    }

    /**
     * Dropdown button
     */
    @computed get dropdownButton() {
        const active: string = StrCast(this.rootDoc.dropDownOpen);
        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
        return (
            <div className={`menuButton ${this.type} ${active}`}
                style={{ color: color, backgroundColor: backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
                onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}>
                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>}
                <div
                    className="menuButton-dropdown"
                    style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
                    <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
                </div>
                {this.rootDoc.dropDownOpen ?
                    <div className="menuButton-dropdownBox">
                        {/* DROPDOWN BOX CONTENTS */}
                    </div> : null}
            </div>
        );
    }

    /**
     * Dropdown list
     */
    @computed get dropdownListButton() {
        const active: string = StrCast(this.rootDoc.dropDownOpen);
        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);

        const script = ScriptCast(this.rootDoc.script);

        let noviceList: string[] = [];
        let text: string | undefined;
        let dropdown = true;
        let icon: IconProp = "caret-down";
        try {
            if (script.script.originalScript.startsWith('setView')) {
                const selected = SelectionManager.Docs().lastElement();
                if (selected) {
                    if (StrCast(selected.type) === DocumentType.COL) {
                        text = StrCast(selected._viewType);
                    } else {
                        dropdown = false;
                        text = selected.type === DocumentType.RTF ? "Text" : StrCast(selected.type);
                        icon = Doc.toIcon(selected);
                    }
                } else {
                    dropdown = false;
                    icon = "globe-asia";
                    text = "User Default";
                }
                noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking];
            } else if (script.script.originalScript.startsWith('setFont')) {
                const editorView = RichTextMenu.Instance?.TextView?.EditorView;
                text = StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
                noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia",
                    "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"];
            }
        } catch (e) {
            console.log(e);
        }

        // Get items to place into the list
        const list = this.buttonList.map((value) => {
            if (Doc.UserDoc().noviceMode && !noviceList.includes(value)) {
                return;
            }
            return <div className="list-item" key={`${value}`}
                style={{
                    fontFamily: script.script.originalScript.startsWith('setFont') ? value : undefined,
                    backgroundColor: value === text ? Colors.LIGHT_BLUE : undefined
                }}
                onClick={() => script.script.run({ value }).result}>
                {value[0].toUpperCase() + value.slice(1)}
            </div>;
        });

        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
            <div className="fontIconBox-label" style={{ bottom: 0, position: "absolute", color: color, backgroundColor: backgroundColor }}>
                {this.label}
            </div>;

        return (
            <div className={`menuButton ${this.type} ${active}`}
                style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : "flex" }}
                onClick={dropdown ? () => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}>
                {dropdown ? (null) : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
                <div className="menuButton-dropdown-header">
                    {text && text[0].toUpperCase() + text.slice(1)}
                </div>
                {label}
                {!dropdown ? (null) : <div className="menuButton-dropDown">
                    <FontAwesomeIcon icon={icon} color={color} size="sm" />
                </div>}
                {this.rootDoc.dropDownOpen ?
                    <div>
                        <div className="menuButton-dropdownList"
                            style={{ left: 0 }}>
                            {list}
                        </div>
                        <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
                    </div>
                    : null}
            </div>
        );
    }

    @observable colorPickerClosed: boolean = true;
    @computed get colorScript() { return ScriptCast(this.rootDoc.script); }

    colorPicker = (curColor: string) => {
        const change = (value: ColorState) => {
            const s = this.colorScript;
            s && undoBatch(() => s.script.run({ value: Utils.colorString(value), _readOnly_: false }).result)();
        };
        const presets = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
            '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
            '#FFFFFF', '#f1efeb', "transparent"];
        return <SketchPicker
            onChange={change}
            color={curColor}
            presetColors={presets} />;
    }
    /**
     * Color button
     */
    @computed get colorButton() {
        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
        const curColor = this.colorScript?.script.run({ value: undefined, _readOnly_: true }).result ?? "transparent";

        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
            <div className="fontIconBox-label" style={{ color, backgroundColor }}>
                {this.label}
            </div>;

        const dropdownCaret = <div
            className="menuButton-dropDown"
            style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
            <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
        </div>;
        setTimeout(() => this.colorPicker(curColor)); // cause an update to the color picker rendered in MainView
        return (
            <div className={`menuButton ${this.type + (Doc.UserDoc()._showLabel ? "Label" : "")} ${this.colorPickerClosed}`}
                style={{ color: color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
                onClick={action(() => this.colorPickerClosed = !this.colorPickerClosed)}
                onPointerDown={e => e.stopPropagation()}>
                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                <div className="colorButton-color" style={{ backgroundColor: curColor }} />
                {label}
                {/* {dropdownCaret} */}
                {this.colorPickerClosed ? (null) :
                    <div>
                        <div className="menuButton-dropdownBox"
                            onPointerDown={e => e.stopPropagation()}
                            onClick={e => e.stopPropagation()}>
                            {this.colorPicker(curColor)}
                        </div>
                        <div className="dropbox-background" onClick={action((e) => {
                            e.stopPropagation(); this.colorPickerClosed = true;
                        })} />
                    </div>}
            </div>
        );
    }

    @computed get toggleButton() {
        // Determine the type of toggle button
        const switchToggle: boolean = BoolCast(this.rootDoc.switchToggle);
        const buttonText: string = StrCast(this.rootDoc.buttonText);
        // Colors
        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);

        // Button label
        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
            <div className="fontIconBox-label" style={{ color, backgroundColor }}>
                {this.label}
            </div>;

        if (switchToggle) {
            return (
                <div className={`menuButton ${this.type} ${'switch'}`}>
                    {buttonText ? buttonText : null}
                    <label className="switch">
                        <input type="checkbox"
                            checked={backgroundColor === Colors.MEDIUM_BLUE}
                        />
                        <span className="slider round" />
                    </label>
                </div>
            );
        } else {
            return (
                <div className={`menuButton ${this.type + (Doc.UserDoc()._showLabel ? "Label" : "")}`}
                    style={{ opacity: 1, backgroundColor, color }}>
                    <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                    {label}
                </div>
            );
        }
    }



    /**
     * Default
     */
    @computed get defaultButton() {
        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
        const active: string = StrCast(this.rootDoc.dropDownOpen);
        return (
            <div className={`menuButton ${this.type}`} onContextMenu={this.specificContextMenu}
                style={{ backgroundColor: "transparent", borderBottomLeftRadius: this.dropdown ? 0 : undefined }}>
                <div className="menuButton-wrap">
                    <FontAwesomeIcon className={`menuButton-icon-${this.type}`} icon={this.icon} color={"black"} size={"sm"} />
                    {!this.label || !Doc.UserDoc()._showLabel ? (null) :
                        <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>}
                </div>
            </div>
        );
    }

    @computed get editableText() {
        // Script for running the toggle
        const script = ScriptCast(this.rootDoc.script);
        // Function to run the script
        const checkResult = script?.script.run({ value: "", _readOnly_: true }).result;

        const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result;
        return (
            <div className="menuButton editableText">
                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"lock"} />
                <div style={{ width: "calc(100% - .875em)", paddingLeft: "4px" }}>
                    <EditableView GetValue={() => script?.script.run({ value: "", _readOnly_: true }).result} SetValue={setValue} contents={checkResult} />
                </div>
            </div>
        );
    }

    render() {
        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
            <div className="fontIconBox-label" style={{ color, backgroundColor }}>
                {this.label}
            </div>;

        const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) :
            <div className="fontIconBox-label" style={{ color, backgroundColor: "transparent" }}>
                {this.label}
            </div>;

        const buttonText = StrCast(this.rootDoc.buttonText);

        // TODO:glr Add label of button type
        let button = this.defaultButton;

        switch (this.type) {
            case ButtonType.TextButton:
                button = (
                    <div className={`menuButton ${this.type}`} style={{ color, backgroundColor, opacity: 1, gridAutoColumns: `${NumCast(this.rootDoc._height)} auto` }}>
                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                        {buttonText ?
                            <div className="button-text">
                                {buttonText}
                            </div>
                            : null}
                        {label}
                    </div>
                );
                // button = <TextButton {...buttonProps}></TextButton>
                break;
            case ButtonType.EditableText:
                button = this.editableText;
                break;
            case ButtonType.NumberButton:
                button = this.numberButton;
                break;
            case ButtonType.DropdownButton:
                button = this.dropdownButton;
                break;
            case ButtonType.DropdownList:
                button = this.dropdownListButton;
                break;
            case ButtonType.ColorButton:
                button = this.colorButton;
                break;
            case ButtonType.ToolButton:
                button = (
                    <div className={`menuButton ${this.type + (Doc.UserDoc()._showLabel ? "Label" : "")}`} style={{ opacity: 1, backgroundColor, color }}>
                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                        {label}
                    </div>
                );
                break;
            case ButtonType.ToggleButton:
                button = this.toggleButton;
                // button = <ToggleButton {...buttonProps}></ToggleButton>
                break;
            case ButtonType.ClickButton:
                button = (
                    <div className={`menuButton ${this.type + (Doc.UserDoc()._showLabel ? "Label" : "")}`} style={{ color, backgroundColor, opacity: 1 }}>
                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                        {label}
                    </div>
                );
                break;
            case ButtonType.MenuButton:
                const trailsIcon = <img src={`/assets/${"presTrails.png"}`}
                    style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? "0%" : "100%"})` }} />;
                button = (
                    <div className={`menuButton ${this.type}`} style={{ color, backgroundColor }}>
                        {this.icon === "pres-trail" ? trailsIcon : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />}
                        {menuLabel}
                        <FontIconBadge collection={Cast(this.rootDoc.watchedDocuments, Doc, null)} />
                    </div >
                );
                break;
            default:
                break;
        }

        return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton || this.type === ButtonType.NumberButton || this.type === ButtonType.EditableText ? button :
            <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>
                {button}
            </Tooltip>;
    }
}


// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setView(view: string) {
    const selected = SelectionManager.Docs().lastElement();
    selected ? selected._viewType = view : console.log("[FontIconBox.tsx] changeView failed");
});


// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
    const selected = SelectionManager.Docs().lastElement();
    if (checkResult) {
        return selected?._backgroundColor ?? "transparent";
    }
    if (selected) selected._backgroundColor = color;
});

// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) {
    if (checkResult) {
        return Doc.SharingDoc().userColor;
    }
    Doc.SharingDoc().userColor = undefined;
    Doc.GetProto(Doc.SharingDoc()).userColor = color;
    Doc.UserDoc().showTitle = color === "transparent" ? undefined : StrCast(Doc.UserDoc().showTitle, "creationDate");
});

// toggle: Set overlay status of selected document
ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
    if (checkResult && selected) {
        if (NumCast(selected.Document.z) >= 1) return Colors.MEDIUM_BLUE;
        return "transparent";
    }
    selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed");
});

/** TEXT
 *      setFont
 *      setFontSize
 *      toggleBold
 *      toggleUnderline
 *      toggleItalic
 *      setAlignment
 *      toggleBold
 *      toggleItalic
 *      toggleUnderline
 **/

// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setFont(font: string, checkResult?: boolean) {
    SelectionManager.Docs().map(doc => doc._fontFamily = font);
    const editorView = RichTextMenu.Instance.TextView?.EditorView;
    if (checkResult) {
        return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
    }
    if (editorView) RichTextMenu.Instance.setFontFamily(font);
    else Doc.UserDoc().fontFamily = font;
});

ScriptingGlobals.add(function getActiveTextInfo(info: "family" | "size" | "color" | "highlight") {
    const editorView = RichTextMenu.Instance.TextView?.EditorView;
    const style = editorView?.state && RichTextMenu.Instance.getActiveFontStylesOnSelection();
    switch (info) {
        case "family": return style?.activeFamilies[0];
        case "size": return style?.activeSizes[0];
        case "color": return style?.activeColors[0];
        case "highlight": return style?.activeHighlights[0];
    }
});

ScriptingGlobals.add(function setAlignment(align: "left" | "right" | "center", checkResult?: boolean) {
    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
    if (checkResult) {
        return (editorView ? RichTextMenu.Instance.textAlign : Doc.UserDoc().textAlign) === align ? Colors.MEDIUM_BLUE : "transparent";
    }
    if (editorView?.state) RichTextMenu.Instance.align(editorView, editorView.dispatch, align);
    else Doc.UserDoc().textAlign = align;
});

ScriptingGlobals.add(function setBulletList(mapStyle: "bullet" | "decimal", checkResult?: boolean) {
    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
    if (checkResult) {
        const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle();
        if (active === mapStyle) return Colors.MEDIUM_BLUE;
        return "transparent";
    }
    if (editorView) {
        const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle();
        editorView?.state && RichTextMenu.Instance.changeListType(
            editorView.state.schema.nodes.ordered_list.create({ mapStyle: active === mapStyle ? "" : mapStyle }));
    }
});

// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setFontColor(color?: string, checkResult?: boolean) {
    const editorView = RichTextMenu.Instance?.TextView?.EditorView;

    if (checkResult) {
        return editorView ? RichTextMenu.Instance.fontColor : Doc.UserDoc().fontColor;
    }

    if (editorView) color && RichTextMenu.Instance.setColor(color, editorView, editorView?.dispatch);
    else Doc.UserDoc().fontColor = color;
});

// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setFontHighlight(color?: string, checkResult?: boolean) {
    const selected = SelectionManager.Docs().lastElement();
    const editorView = RichTextMenu.Instance.TextView?.EditorView;

    if (checkResult) {
        return (selected ?? Doc.UserDoc())._fontHighlight;
    }
    if (selected) {
        selected._fontColor = color;
        if (color) {
            editorView?.state && RichTextMenu.Instance.setHighlight(color, editorView, editorView?.dispatch);
        }
    }
    Doc.UserDoc()._fontHighlight = color;
});

// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setFontSize(size: string | number, checkResult?: boolean) {
    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
    if (checkResult) {
        return RichTextMenu.Instance.fontSize.replace("px", "");
    }
    if (typeof size === "number") size = size.toString();
    if (size && Number(size).toString() === size) size += "px";
    if (editorView) RichTextMenu.Instance.setFontSize(size);
    else Doc.UserDoc()._fontSize = size;
});
ScriptingGlobals.add(function toggleNoAutoLinkAnchor(checkResult?: boolean) {
    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
    if (checkResult) {
        return (editorView ? RichTextMenu.Instance.noAutoLink : Doc.UserDoc().noAutoLink) ? Colors.MEDIUM_BLUE : "transparent";
    }
    if (editorView) RichTextMenu.Instance?.toggleNoAutoLinkAnchor();
    else Doc.UserDoc().noAutoLink = Doc.UserDoc().noAutoLink ? true : false;
});

ScriptingGlobals.add(function toggleBold(checkResult?: boolean) {
    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
    if (checkResult) {
        return (editorView ? RichTextMenu.Instance.bold : Doc.UserDoc().fontWeight === "bold") ? Colors.MEDIUM_BLUE : "transparent";
    }
    if (editorView) RichTextMenu.Instance?.toggleBold();
    else Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === "bold" ? undefined : "bold";
});

ScriptingGlobals.add(function toggleUnderline(checkResult?: boolean) {
    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
    if (checkResult) {
        return (editorView ? RichTextMenu.Instance.underline : Doc.UserDoc().textDecoration === "underline") ? Colors.MEDIUM_BLUE : "transparent";
    }
    if (editorView) RichTextMenu.Instance?.toggleUnderline();
    else Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === "underline" ? undefined : "underline";
});

ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) {
    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
    if (checkResult) {
        return (editorView ? RichTextMenu.Instance.italics : Doc.UserDoc().fontStyle === "italics") ? Colors.MEDIUM_BLUE : "transparent";
    }
    if (editorView) RichTextMenu.Instance?.toggleItalics();
    else Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === "italics" ? undefined : "italics";
});




/** INK
 *      setActiveInkTool
 *      setStrokeWidth
 *      setStrokeColor
 **/

ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boolean) {
    if (checkResult) {
        return ((Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool) ?
            Colors.MEDIUM_BLUE : "transparent";
    }
    if (["circle", "square", "line"].includes(tool)) {
        if (GestureOverlay.Instance.InkShape === tool) {
            Doc.UserDoc().activeInkTool = InkTool.None;
            GestureOverlay.Instance.InkShape = InkTool.None;
        } else {
            Doc.UserDoc().activeInkTool = InkTool.Pen;
            GestureOverlay.Instance.InkShape = tool;
        }
    } else if (tool) { // pen or eraser
        if (Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance.InkShape) {
            Doc.UserDoc().activeInkTool = InkTool.None;
        } else {
            Doc.UserDoc().activeInkTool = tool;
            GestureOverlay.Instance.InkShape = "";
        }
    } else {
        Doc.UserDoc().activeInkTool = InkTool.None;
    }
});

// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setFillColor(color?: string, checkResult?: boolean) {
    const selected = SelectionManager.Docs().lastElement();
    if (checkResult) {
        if (selected?.type === DocumentType.INK) {
            return StrCast(selected.fillColor);
        }
        return ActiveFillColor();
    }
    SetActiveFillColor(StrCast(color));
    SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.fillColor = color);
});

ScriptingGlobals.add(function setStrokeWidth(width: number, checkResult?: boolean) {
    if (checkResult) {
        const selected = SelectionManager.Docs().lastElement();
        if (selected?.type === DocumentType.INK) {
            return NumCast(selected.strokeWidth);
        }
        return ActiveInkWidth();
    }
    SetActiveInkWidth(width.toString());
    SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.strokeWidth = Number(width));
});

// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setStrokeColor(color?: string, checkResult?: boolean) {
    if (checkResult) {
        const selected = SelectionManager.Docs().lastElement();
        if (selected?.type === DocumentType.INK) {
            return StrCast(selected.color);
        }
        return ActiveInkColor();
    }
    SetActiveInkColor(StrCast(color));
    SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.color = String(color));
});


/** WEB
 *      webSetURL
 **/
ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
    const selected = SelectionManager.Views().lastElement();
    if (selected?.rootDoc.type === DocumentType.WEB) {
        if (checkResult) {
            return StrCast(selected.rootDoc.data, Cast(selected.rootDoc.data, WebField, null)?.url?.href);
        }
        (selected.ComponentView as WebBox).submitURL(url);
        //selected.rootDoc.data = new WebField(url);
    }
});
ScriptingGlobals.add(function webForward(checkResult?: boolean) {
    const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox);
    if (checkResult) {
        return selected?.forward(checkResult) ? undefined : "lightGray";
    }
    selected?.forward();
});
ScriptingGlobals.add(function webBack(checkResult?: boolean) {
    const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox);
    if (checkResult) {
        return selected?.back(checkResult) ? undefined : "lightGray";
    }
    selected?.back();
});


/** Schema
 *      toggleSchemaPreview
 **/
ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
    const selected = SelectionManager.Docs().lastElement();
    if (checkResult && selected) {
        const result: boolean = NumCast(selected.schemaPreviewWidth) > 0;
        if (result) return Colors.MEDIUM_BLUE;
        else return "transparent";
    }
    else if (selected) {
        if (NumCast(selected.schemaPreviewWidth) > 0) {
            selected.schemaPreviewWidth = 200;
        } else {
            selected.schemaPreviewWidth = 0;
        }
    }
});

/** STACK
 *      groupBy
 */
ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) {
    SelectionManager.Docs().map(doc => doc._fontFamily = key);
    const editorView = RichTextMenu.Instance.TextView?.EditorView;
    if (checkResult) {
        return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
    }
    if (editorView) RichTextMenu.Instance.setFontFamily(key);
    else Doc.UserDoc().fontFamily = key;
});