import { action, computed, } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, StrListCast } from '../../../../../fields/Doc';
import { List } from '../../../../../fields/List';
import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../../Utils';
import { DragManager } from '../../../../util/DragManager';
import { DocumentView } from '../../DocumentView';
import { DataVizView } from '../DataVizBox';
import { LinkManager } from '../../../../util/LinkManager';
import { Cast, DocCast } from '../../../../../fields/Types';
import './Chart.scss';
import { listSpec } from '../../../../../fields/Schema';

interface TableBoxProps {
    rootDoc: Doc;
    layoutDoc: Doc;
    pairs: { [key: string]: any }[];
    selectAxes: (axes: string[]) => void;
    axes: string[];
    width: number;
    height: number;
    margin: {
        top: number;
        right: number;
        bottom: number;
        left: number;
    };
    docView?: () => DocumentView | undefined;
}

@observer
export class TableBox extends React.Component<TableBoxProps> {

    @computed get _tableData() {
        if (this.incomingLinks.length! <= 0) return this.props.pairs;
        return this.props.pairs?.filter(pair => this.incomingLinks[0]!.selected && StrListCast(this.incomingLinks[0].selected).includes(pair.guid))
    }

    @computed get incomingLinks() {
        return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links
            .filter(link => {
                return link.link_anchor_1 == this.props.rootDoc.draggedFrom}) // get links where this chart doc is the target of the link
            .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
    }

    @computed get columns() {
        return this._tableData.length ? Array.from(Object.keys(this._tableData[0])).filter(header => header!='guid' && header!='') : [];
    }

    render() {
        if (this._tableData.length>0){
            return (
                <div className="table-container" style={{height: this.props.height+this.props.margin.top+this.props.margin.bottom}}>
                    <table className="table">
                        <thead>
                            <tr className="table-row">
                                {this.columns
                                    .filter(col => !col.startsWith('select'))
                                    .map(col => {
                                        const header = React.createRef<HTMLElement>();
                                        return (
                                            <th
                                                key={this.columns.indexOf(col)}
                                                ref={header as any}
                                                style={{
                                                    color: this.props.axes.slice().reverse().lastElement() === col ? 'green' : this.props.axes.lastElement() === col ? 'red' : undefined,
                                                    fontWeight: 'bolder', border: '3px solid black'
                                                }}
                                                onPointerDown={e => {
                                                    const downX = e.clientX;
                                                    const downY = e.clientY;
                                                    setupMoveUpEvents(
                                                        {},
                                                        e,
                                                        e => {
                                                            const sourceAnchorCreator = () => this.props.docView?.()!.rootDoc!;
                                                            const targetCreator = (annotationOn: Doc | undefined) => {
                                                                const embedding = Doc.MakeEmbedding(this.props.docView?.()!.rootDoc!);
                                                                embedding._dataVizView = DataVizView.TABLE;
                                                                embedding._data_vizAxes = new List<string>([col, col]);
                                                                embedding._draggedFrom = this.props.docView?.()!.rootDoc!;
                                                                embedding.annotationOn = annotationOn; //this.props.docView?.()!.rootDoc!;
                                                                return embedding;
                                                            };
                                                            if (this.props.docView?.() && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) {
                                                                DragManager.StartAnchorAnnoDrag([header.current!], new DragManager.AnchorAnnoDragData(this.props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, {
                                                                    dragComplete: e => {
                                                                        if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) {
                                                                            e.linkDocument.link_displayLine = true;
                                                                            e.linkDocument.link_matchEmbeddings = true;
                                                                            // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc;
                                                                            // e.annoDragData.linkSourceDoc.followLinkZoom = false;
                                                                        }
                                                                    },
                                                                });
                                                                return true;
                                                            }
                                                            return false;
                                                        },
                                                        emptyFunction,
                                                        action(e => {
                                                            const newAxes = this.props.axes;
                                                            if (newAxes.includes(col)) {
                                                                newAxes.splice(newAxes.indexOf(col), 1);
                                                            } else if (newAxes.length >= 1) {
                                                                newAxes[1] = col;
                                                            } else {
                                                                newAxes[0] = col;
                                                            }
                                                            this.props.selectAxes(newAxes);
                                                        })
                                                    );
                                                }}>
                                                {col}
                                            </th>
                                        );
                                    })}
                            </tr>
                        </thead>
                        <tbody>
                            {this._tableData?.map((p, i) => {
                                var containsData = false;
                                this.columns.map(col => {if (p[col]!='' && p[col]!=null && p[col]!=undefined) containsData = true})
                                if (containsData){
                                    return (
                                        <tr key={i} className="table-row" onClick={action(e => {
                                                if (!this.props.layoutDoc.selected) this.props.layoutDoc.selected = new List<string>();
                                                const selected = Cast(this.props.layoutDoc.selected, listSpec("string"), null);
                                                if (selected.includes(p.guid)) selected.splice(selected.indexOf(p.guid), 1);
                                                else {
                                                    selected.push(p.guid)};
                                            })} style={
                                                { fontWeight: StrListCast(this.props.layoutDoc.selected).includes(p.guid) ? 'bold' : '' , width: '110%',
                                                background: StrListCast(this.props.layoutDoc.selected).includes(p.guid) ? 'lightgrey' : '' }}>
                                            {this.columns.map(col => (
                                                (this.props.layoutDoc.selected)?
                                                    <td key={this.columns.indexOf(col)} style={{border: '1px solid black'}}>
                                                        {p[col]}
                                                    </td>
                                                : <td key={this.columns.indexOf(col)} style={{border: '1px solid black'}}> {p[col]} </td>
                                            ))}
                                        </tr>
                                    );
                                }
                            })}
                        </tbody>
                    </table>
                </div>
            );
        }
        else return (
            <div className='chart-container'>
                Selected rows of data from the incoming DataVizBox to display.
            </div>
        )
    }
}
