import { IconButton, Size } from 'browndash-components';
import { computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
import * as React from 'react';
import { CgClose, CgLock, CgLockUnlock, CgMenu } from 'react-icons/cg';
import { FaExternalLinkAlt } from 'react-icons/fa';
import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
import { emptyFunction } from '../../../../Utils';
import { Doc, DocListCast, FieldResult } from '../../../../fields/Doc';
import { BoolCast } from '../../../../fields/Types';
import { Transform } from '../../../util/Transform';
import { undoable } from '../../../util/UndoManager';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { Colors } from '../../global/globalEnums';
import { FieldView, FieldViewProps } from '../../nodes/FieldView';
import { OpenWhere } from '../../nodes/OpenWhere';
import { CollectionSchemaView } from './CollectionSchemaView';
import './CollectionSchemaView.scss';
import { SchemaTableCell } from './SchemaTableCell';
import { ContextMenu } from '../../ContextMenu';
import { CollectionFreeFormView } from '../collectionFreeForm';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IconProp } from '@fortawesome/fontawesome-svg-core';

interface SchemaRowBoxProps extends FieldViewProps {
    rowIndex: number;
}
@observer
export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
    public static LayoutString(fieldKey: string, rowIndex: number) {
        return FieldView.LayoutString(SchemaRowBox, fieldKey).replace('fieldKey', `rowIndex={${rowIndex}} fieldKey`);
    }
    private _ref: HTMLDivElement | null = null;
    @observable _childrenAddedToSchema: boolean = false;

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

    bounds = () => this._ref?.getBoundingClientRect();

    @computed get schemaView() {
        return this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionSchemaView;
    }

    @computed get schemaDoc() {
        return this.schemaView.Document;
    }

    @computed get rowIndex() {
        return this.schemaView?.rowIndex(this.Document) ?? -1;
    }

    componentDidMount(): void {
        this._props.setContentViewBox?.(this);
    }

    openContextMenu = (x: number, y: number) => {
        ContextMenu.Instance.clearItems();
        ContextMenu.Instance.addItem({
            description: `Close doc`,
            event: () => this.schemaView.removeDoc(this.Document),
            icon: 'minus',
        });
        ContextMenu.Instance.addItem({
            description: this.Document._lockedSchemaEditing ? 'Unlock field editing' : 'Lock field editing',
            event: () => this.Document._lockedSchemaEditing = !this.Document._lockedSchemaEditing,
            icon: this.Document._lockedSchemaEditing ? 'lock-open' : 'lock',
        });
        ContextMenu.Instance.addItem({
            description: 'Open preview',
            event: () => this._props.addDocTab(this.Document, OpenWhere.addRight),
            icon: 'magnifying-glass',
        });
        const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)])
        if (this.Document.type === 'collection' && childDocs.length) {
                ContextMenu.Instance.addItem({
                description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
                event: () => {
                    this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; 
                },
                icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus',
            });
        }
        ContextMenu.Instance.displayMenu(x, y, undefined, false);
    }

    @computed get menuBackgroundColor(){
        if (this.Document._lockedSchemaEditing){
            if (this._props.isSelected()) return '#B0D1E7'
            else return '#F5F5F5'
        }   
        return ''
    }

    @computed get menuInfos() {
        const infos: Array<IconProp> = [];
        if (this.Document._lockedSchemaEditing) infos.push('lock');
        if (this.Document._childrenSharedWithSchema) infos.push('star');
        return infos;
    }

    @computed get isolatedSelection() {
        const toReturn: [boolean, boolean] = [true, true];
        const docs = this.schemaView.docsWithDrag.docs;
        const selectedBelow: boolean = this.schemaView?._selectedDocs.includes(docs[this.rowIndex + 1]);
        const selectedAbove: boolean = this.schemaView?._selectedDocs.includes(docs[this.rowIndex - 1]);
        toReturn[0] = selectedAbove;
        toReturn[1] = selectedBelow;
        return toReturn;
    }

    setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY);
    selectedCol = () => this.schemaView._selectedCol;
    getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey));
    selectCell = (doc: Doc, col: number, shift: boolean, ctrl: boolean) => this.schemaView?.selectCell(doc, col, shift, ctrl);
    deselectCell = () => this.schemaView?.deselectAllCells();
    selectedCells = () => this.schemaView?._selectedDocs;
    setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false;
    columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
    computeRowIndex = () => this.schemaView?.rowIndex(this.Document);
    highlightCells = (text: string) => this.schemaView?.highlightCells(text);
    render() {
        return (
            <div
                className="schema-row"
                onPointerDown={e => this.setCursorIndex(e.clientY)}
                style={{ height: this._props.PanelHeight(), backgroundColor: this._props.isSelected() ? Colors.LIGHT_BLUE : undefined }}
                ref={(row: HTMLDivElement | null) => {
                    row && this.schemaView?.addRowRef?.(this.Document, row);
                    this._ref = row;
                }}>
                <div
                    className="row-menu"
                    style={{
                        width: CollectionSchemaView._rowMenuWidth,
                        pointerEvents: !this._props.isContentActive() ? 'none' : undefined,
                        backgroundColor: this.menuBackgroundColor
                    }}>
                    <IconButton
                        tooltip="Open actions menu"
                        icon={ <FontAwesomeIcon icon="caret-right" size='lg'/>}
                        size={Size.XSMALL}
                        color={'black'}
                        onPointerDown={e =>
                            setupMoveUpEvents(
                                this,
                                e,
                                returnFalse,
                                emptyFunction,
                                undoable(clickEv => {
                                    clickEv.stopPropagation();
                                    this.openContextMenu(e.clientX, e.clientY)
                                }, 'open actions menu')
                            )
                        }
                    />
                <div className="row-menu-infos">
                    {this.menuInfos.map(icn => <FontAwesomeIcon className="row-infos-icon" icon={icn} size='2xs' />)}
                </div>
                </div>
                <div className="row-cells">
                    {this.schemaView?.columnKeys?.map((key, index) => (
                        <SchemaTableCell
                            highlightCells={this.highlightCells}
                            isolatedSelection={this.isolatedSelection}
                            key={key}
                            rowSelected={this._props.isSelected}
                            Document={this.Document}
                            col={index}
                            fieldKey={key}
                            allowCRs={false} // to enter text with new lines, must use \n
                            columnWidth={this.columnWidth(index)}
                            rowHeight={this.schemaView.rowHeightFunc}
                            isRowActive={this._props.isContentActive}
                            getFinfo={this.getFinfo}
                            selectCell={this.selectCell}
                            deselectCell={this.deselectCell}
                            selectedCells={this.selectedCells}
                            selectedCol={this.selectedCol}
                            setColumnValues={this.setColumnValues}
                            oneLine={BoolCast(this.schemaDoc?._singleLine)}
                            menuTarget={this.schemaView.MenuTarget}
                            transform={() => {
                                const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index;
                                const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0);
                                const y = (this._props.rowIndex ?? 0) * this._props.PanelHeight();
                                return new Transform(x + CollectionSchemaView._rowMenuWidth, y, 1);
                            }}
                        />
                    ))}
                </div>
            </div>
        );
    }
}
