import * as React from "react";

import { observer } from "mobx-react";

import { DSComponent, DSBaseProps } from "@dewesoft-web/ui";

import { Dialog } from "react-toolbox";

import { DSGridModel } from "./model/DSGridModel";
import { ColumnSelector } from "./ColumnSelector";

import * as theme from "./DSGrid.scss";

import { GroupData } from "./group/data/GroupData";
import { GridGroupExpander } from "./group/expander/GridGroupExpander";

import ClassAttributes = React.ClassAttributes;

import { ChooseColumns } from "./columns/ChooseColumns";
import { ColumnContextMenus } from "./context/ColumnContextMenues";
import { ChooseColumnsModel } from "./columns/ChooseColumnsModel";

const Headers = require("./headers/GridHeaders");

export interface DSGridProps extends DSBaseProps {
    model? : DSGridModel;
    showColumnSelector? : boolean;
    showButtons? : boolean;
    showGroups? : boolean;
    name ? : string;
}

interface DSGridTableProps {
    model : DSGridModel;
    height : string | number;
    style : any;
}

const PAGE_UP = 33;
const PAGE_DOWN = 34;
const HOME = 36;
const END = 35;
const ARROW_UP = 38;
const ARROW_DOWN = 40;

let counter = 0;

@observer
class DSGridTable extends React.Component<DSGridTableProps, any> {

    props : DSGridTableProps;

    tabIndex : number;

    constructor(props : DSGridTableProps) {
        super(props);

        this.tabIndex = counter++;

        this.handleKey = this.handleKey.bind(this);
    }

    handleKey(e : any) {
        if (e.target instanceof HTMLInputElement) {
            return;
        }

        const model : DSGridModel = this.props.model;

        switch (e.keyCode) {
            case ARROW_UP:
                model.selectPreviousRow();
                break;
            case ARROW_DOWN:
                model.selectNextRow();
                break;
            case PAGE_UP:
            case HOME:
                model.selectFirstRow();
                break;
            case PAGE_DOWN:
            case END:
                model.selectLastRow();
                break;
            default:
                break;
        }

        e.preventDefault();
    }

    getData() {
        const model = this.props.model;
        const rows = model.rowsByGroup;

        const showGroups = model.showGroups;

        return model.groups.map((group) => {
            return [
                <GridGroupExpander group={group} show={showGroups}/>,
                <GroupData rows={rows[group.name]}
                           columns={model.sortedColumns}
                           showGroups={showGroups}
                           show={group.expanded}
                           onEditCell={model.editCell}
                           onTrySelect={model.onTrySelect}
                           onStartSelect={model.startSelect}
                           onChangeData={model.setSelectedColumnData}
                           onRowSelect={model.onRowSelect}
                />
            ];
        });
    }

    render() {
        const { model, style : userStyles, ...props } = this.props;

        const showGroups = model.showGroups;
        const classNames = [theme.dsGrid, showGroups ? theme.grouped : null].join(" ").trim();

        const style : React.CSSProperties = {
            height: "500px",
            overflow: "auto",
            position: "relative",
            ...userStyles
        };

        return (
            <div style={style}>
                <table ref={(e) => this.props.model.setElement(e)}
                       className={classNames}
                       onMouseUp={model.endSelect}
                       onKeyDown={this.handleKey}
                       tabIndex={this.tabIndex}
                >
                    <Headers.GridHeaders showGroups={model.showGroups}
                                         columns={model.sortedColumns}
                                         onColumnClicked={model.selectWholeColumn}
                                         selectedColumn={model.selectedColumn}
                    />
                    {
                        this.getData()
                    }
                </table>
            </div>
        );
    }
}


@DSComponent
export class DSGrid extends React.Component<DSGridProps, any> {

    model : DSGridModel;

    props : DSGridProps;

    private actions : any[];

    constructor(props : DSGridProps) {
        super(props);

        if (this.props.model) {
            this.model = this.props.model;
        }
        else {
            this.model = new DSGridModel([], [], this.props.name);
        }

        this.handleToggle = this.handleToggle.bind(this);
        this.unsortColumn = this.unsortColumn.bind(this);
        this.sortColumn = this.sortColumn.bind(this);
        this.onStartEditColumns = this.onStartEditColumns.bind(this);

        this.state = {
            dialog: false
        };

        this.actions = [
            { label: "Close", onClick: this.handleToggle }
        ];
    }

    unsortColumn(column : string) {
        // console.log("Unsorting column:" + column);

        this.model.unsortColumns();
    }

    sortColumn(column : string) {
        // console.log("Sorting column:" + column);


        this.model.sortColumn(column);
    }

    handleToggle() {
        this.setState({ dialog: false });
    }

    onStartEditColumns() {
        this.setState({ dialog: true });
    }

    render() {
        const { model, showColumnSelector, showButtons, showGroups, ...props } = this.props;

        if (showGroups === false) {
            this.model.setShowGroups(false);
        }

        return (
            <div onContextMenu={() => false}>
                <ColumnSelector model={this.model} groupBySelect={showButtons} groupToggle={showButtons} searchBox={showButtons}/>
                <DSGridTable model={this.model} {...props as any}/>
                <Dialog
                    title="Choose columns"
                    className="grid-col-select"
                    actions={this.actions}
                    active={this.state.dialog}
                    onEscKeyDown={this.handleToggle}
                    onOverlayClick={this.handleToggle}
                >
                    <ChooseColumns model={new ChooseColumnsModel(this.model.columns)}/>
                </Dialog>
                <ColumnContextMenus columns={this.model.columns}
                                    onEditColumns={this.onStartEditColumns}
                                    onSortColumn={this.sortColumn}
                                    onUnsortColumn={this.unsortColumn}
                />
            </div>
        );
    }
}
