import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, FieldResult } from '../../../../fields/Doc';
import { Cast, NumCast, StrCast } from '../../../../fields/Types';
import { CsvField } from '../../../../fields/URLField';
import { Docs } from '../../../documents/Documents';
import { ViewBoxAnnotatableComponent, ViewBoxBaseComponent } from '../../DocComponent';
import { FieldViewProps, FieldView } from '../FieldView';
import { ChartBox } from './ChartBox';
import './DataVizBox.scss';
import { TableBox } from './components/TableBox';

enum DataVizView {
    TABLE = 'table',
    HISTOGRAM = 'histogram',
}

@observer
export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
    // says we have an object and any string
    // 2 ways of doing it
    // @observable private pairs: { [key: string]: number | string | undefined }[] = [];
    // @observable private pairs: { [key: string]: FieldResult }[] = [];
    @observable private pairs: { x: number; y: number }[] = [];
    private _chartBox: ChartBox | undefined;
    // // another way would be store a schema that defines the type of data we are expecting from an imported doc

    // method1() {
    //     this.pairs[0].x = 3;
    // }

    // method() {
    //     // this.pairs[0].x = 3;
    //     // go through the pairs
    //     const x = this.pairs[0].x;
    //     if (typeof x == 'number') {
    //         let x1 = Number(x);
    //         // let x1 = NumCast(x);
    //     }
    // }

    // could use field result
    // [key: string]: FieldResult;
    // instead of numeric x,y in there,

    // TODO: nda - make this use enum values instead
    // @observable private currView: DataVizView = DataVizView.TABLE;

    // TODO: nda - use onmousedown and onmouseup when dragging and changing height and width to update the height and width props only when dragging stops

    setChartBox = (chartBox: ChartBox) => {
        this._chartBox = chartBox;
    };

    @computed get currView() {
        if (this.rootDoc._dataVizView) {
            return StrCast(this.rootDoc._dataVizView);
        } else {
            return 'table';
        }
    }

    scrollFocus = (doc: Doc, smooth: boolean) => {
        // reconstruct the view based on the anchor ->
        // keep track of the datavizbox view and the type of chart we're rendering

        // use dataview to restore part of it and then pass on the rest to the chartbox

        // pseudocode
        setTimeout(() => this._chartBox?.scrollFocus(doc, smooth)); /* smooth parameter true = do animations */
        return 0;
    };

    getAnchor() {
        // store whatever information would allow me to reselect the same thing (store parameters I would pass to get the exact same element)
        const anchor =
            // this._COMPONENTNAME._getAnchor() ??
            this._chartBox?._getAnchor() ??
            Docs.Create.TextanchorDocument({
                /*put in some options*/
            });

        anchor.dataView = this.currView;

        this.addDocument(anchor);
        return anchor;
        // have some other function in code that
    }
    constructor(props: any) {
        super(props);
        if (!this.rootDoc._dataVizView) {
            // TODO: nda - this might not always want to default to "table"
            this.rootDoc._dataVizView = 'table';
        }
    }

    public static LayoutString(fieldKey: string) {
        return FieldView.LayoutString(DataVizBox, fieldKey);
    }

    @computed get selectView() {
        switch (this.currView) {
            case 'table':
                return <TableBox pairs={this.pairs} />;
            case 'histogram':
                return <ChartBox getAnchor={this.getAnchor} setChartBox={this.setChartBox} rootDoc={this.rootDoc} pairs={this.pairs} dataDoc={this.dataDoc} />;
            // case "histogram":
            //     return (<HistogramBox rootDoc={this.rootDoc} pairs={this.pairs}/>)
        }
    }

    @computed get pairVals() {
        return fetch('/csvData?uri=' + this.dataUrl?.url.href).then(res => res.json());
    }

    @computed get dataUrl() {
        return Cast(this.dataDoc[this.fieldKey], CsvField);
    }

    componentDidMount() {
        // this.createPairs();
        this.fetchData();
    }

    fetchData() {
        const uri = this.dataUrl?.url.href;
        fetch('/csvData?uri=' + uri).then(res =>
            res.json().then(
                action(res => {
                    this.pairs = res;
                })
            )
        );
    }

    // handle changing the view using a button
    @action changeViewHandler(e: React.MouseEvent<HTMLButtonElement>) {
        e.preventDefault();
        e.stopPropagation();
        this.rootDoc._dataVizView = this.currView == 'table' ? 'histogram' : 'table';
    }

    render() {
        if (this.pairs.length == 0) {
            return <div>Loading...</div>;
        }

        return (
            <div className="dataViz">
                <button onClick={e => this.changeViewHandler(e)}>Change View</button>
                {this.selectView}
            </div>
        );
    }
}
