import { IconButton, Size } from 'browndash-components';
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
import * as React from 'react';
import { CgClose, CgLock, CgLockUnlock } from 'react-icons/cg';
import { FaExternalLinkAlt } from 'react-icons/fa';
import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
import { emptyFunction } from '../../../../Utils';
import { Doc } 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';

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;

    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);
    }

    cleanupField = (field: string) => this.schemaView.cleanupComputedField(field)
    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;
    setSelectedColumnValues = (field: any, value: any) => this.schemaView?.setSelectedColumnValues(field, value) ?? false;
    columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
    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,
                    }}>
                    <IconButton
                        tooltip="close"
                        icon={<CgClose size="16px" />}
                        size={Size.XSMALL}
                        onPointerDown={e =>
                            setupMoveUpEvents(
                                this,
                                e,
                                returnFalse,
                                emptyFunction,
                                undoable(clickEv => {
                                    clickEv.stopPropagation();
                                    this._props.removeDocument?.(this.Document);
                                }, 'Delete Row')
                            )
                        }
                    />
                    <IconButton
                        tooltip="whether document interactions are enabled"
                        icon={this.Document._lockedPosition ? <CgLockUnlock size="12px" /> : <CgLock size="12px" />}
                        size={Size.XSMALL}
                        onPointerDown={e =>
                            setupMoveUpEvents(
                                this,
                                e,
                                returnFalse,
                                emptyFunction,
                                undoable(clickEv => {
                                    clickEv.stopPropagation();
                                    Doc.toggleLockedPosition(this.Document);
                                }, 'toggle document lock')
                            )
                        }
                    />
                    <IconButton
                        tooltip="open preview"
                        icon={<FaExternalLinkAlt />}
                        size={Size.XSMALL}
                        onPointerDown={e =>
                            setupMoveUpEvents(
                                this,
                                e,
                                returnFalse,
                                emptyFunction,
                                undoable(clickEv => {
                                    clickEv.stopPropagation();
                                    this._props.addDocTab(this.Document, OpenWhere.addRight);
                                }, 'Open schema Doc preview')
                            )
                        }
                    />
                </div>
                <div className="row-cells">
                    {this.schemaView?.columnKeys?.map((key, index) => (
                        <SchemaTableCell
                            key={key}
                            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}
                            setSelectedColumnValues={this.setSelectedColumnValues}
                            oneLine={BoolCast(this.schemaDoc?._singleLine)}
                            menuTarget={this.schemaView.MenuTarget}
                            cleanupField={this.cleanupField}
                            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>
        );
    }
}
