import * as React from 'react';
import { IconButton, Size } from 'browndash-components';
import { computed, makeObservable, override } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
import { CgClose } from 'react-icons/cg';
import { FaExternalLinkAlt } from 'react-icons/fa';
import { Doc } from '../../../../fields/Doc';
import { BoolCast } from '../../../../fields/Types';
import { copyProps, emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils';
import { DragManager } from '../../../util/DragManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { undoable } from '../../../util/UndoManager';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { Colors } from '../../global/globalEnums';
import { OpenWhere } from '../../nodes/DocumentView';
import { FieldView, FieldViewProps } from '../../nodes/FieldView';
import { CollectionSchemaView } from './CollectionSchemaView';
import './CollectionSchemaView.scss';
import { SchemaTableCell } from './SchemaTableCell';

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

    _prevProps: FieldViewProps & SchemaRowBoxProps;
    @override _props: FieldViewProps & SchemaRowBoxProps;
    constructor(props: FieldViewProps & SchemaRowBoxProps) {
        super(props);
        this._props = this._prevProps = props;
        makeObservable(this);
    }
    componentDidUpdate() {
        copyProps(this);
    }

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

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

    @computed get schemaDoc() {
        return this._props.DocumentView?.()._props.docViewPath().lastElement()?.Document;
    }

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

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

    select = (ctrlKey: boolean, shiftKey: boolean) => {
        if (!this.schemaView) return;
        const lastSelected = Array.from(this.schemaView._selectedDocs).lastElement();
        if (shiftKey && lastSelected) this.schemaView.selectRows(this.Document, lastSelected);
        else {
            this._props.select?.(ctrlKey);
        }
    };

    onPointerEnter = (e: any) => {
        if (SnappingManager.IsDragging && this._props.isContentActive()) {
            document.removeEventListener('pointermove', this.onPointerMove);
            document.addEventListener('pointermove', this.onPointerMove);
        }
    };

    onPointerMove = (e: any) => {
        const dragIsRow = DragManager.docsBeingDragged.some(doc => doc.embedContainer === this.schemaDoc); //  this.schemaView?._selectedDocs.has(doc) ?? false;

        if (this._ref && dragIsRow) {
            const rect = this._ref.getBoundingClientRect();
            const y = e.clientY - rect.top; //y position within the element.
            const height = this._ref.clientHeight;
            const halfLine = height / 2;
            if (y <= halfLine) {
                this._ref.style.borderTop = `solid 2px ${Colors.MEDIUM_BLUE}`;
                this._ref.style.borderBottom = '0px';
                this.schemaView?.setDropIndex(this.rowIndex);
            } else if (y > halfLine) {
                this._ref.style.borderTop = '0px';
                this._ref.style.borderBottom = `solid 2px ${Colors.MEDIUM_BLUE}`;
                this.schemaView?.setDropIndex(this.rowIndex + 1);
            }
        }
    };

    onPointerLeave = (e: any) => {
        if (this._ref) {
            this._ref.style.borderTop = '0px';
            this._ref.style.borderBottom = '0px';
        }
        document.removeEventListener('pointermove', this.onPointerMove);
    };

    getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey));
    selectCell = (doc: Doc, col: number) => this.schemaView?.selectCell(doc, col);
    deselectCell = () => this.schemaView?.deselectCell();
    selectedCell = () => this.schemaView?._selectedCell;
    setColumnValues = (field: any, value: any) => this.schemaView?.setColumnValues(field, value) ?? false;
    columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
    render() {
        return (
            <div
                className="schema-row"
                style={{ height: this._props.PanelHeight(), backgroundColor: this._props.isSelected() ? Colors.LIGHT_BLUE : undefined }}
                onPointerEnter={this.onPointerEnter}
                onPointerLeave={this.onPointerLeave}
                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(e => {
                                    e.stopPropagation();
                                    this._props.removeDocument?.(this.Document);
                                }, 'Delete Row')
                            )
                        }
                    />
                    <IconButton
                        tooltip="open preview"
                        icon={<FaExternalLinkAlt />}
                        size={Size.XSMALL}
                        onPointerDown={e =>
                            setupMoveUpEvents(
                                this,
                                e,
                                returnFalse,
                                emptyFunction,
                                undoable(e => {
                                    e.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}
                            selectedCell={this.selectedCell}
                            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>
        );
    }
}
