/**
 * Created by rburson on 8/11/16.
 */
import * as React from 'react'
import {
    CvActionFiredResult,
    CvState,
    CvProps,
    CvBaseMixin,
    CvContext,
    CvNavigationResult,
    CvSearchPane,
    CvSearchPaneCallback,
    CvRecord,
    CvStateChangeResult,
    CvEvent,
    CvValueProvider,
    CvActionHandlerParams,
    SORT_DIRECTION_SUFFIX,
    SORT_SEQUENCE_SUFFIX,
    FILTER_OPERATOR_SUFFIX,
    FILTER_VALUE_SUFFIX
} from 'catreact'

import {
    CvCellValueDef,
    CvAttributeCellValueDef,
    CvDataAnno,
    CvDetailsPanelCommitCancelControls
} from './catreact-html'
import {
    FormContext,
    EntityRec,
    DetailsContext,
    CellValueDef,
    CellDef,
    LabelCellValueDef, AttributeCellValueDef, ArrayUtil, TabCellValueDef
} from 'catavolt-sdk'

export interface CvSearchPanelState extends CvState {
}

/**
 * Search Panel Properties
 */
export interface CvSearchPanelProps extends CvProps {
    formContext?:FormContext;
    paneRef?:number;
    detailsContext?:DetailsContext;
    navigationListeners?:Array<(event:CvEvent<CvNavigationResult>)=>void>;
    stateChangeListeners?:Array<(event:CvEvent<CvStateChangeResult>)=>void>;
    actionListeners?:Array<(event:CvEvent<CvActionFiredResult>)=>void>;
    actionProvider?:CvValueProvider<CvActionHandlerParams>;
}

/**
 * Renders a Search Panel, styled by CSS
 */
export var CvSearchPanel = React.createClass<CvSearchPanelProps, CvSearchPanelState>({

    mixins: [CvBaseMixin],

    render: function () {

        return  <CvSearchPane {...this.props} detailsRenderer={(cvContext:CvContext,
                             record:EntityRec, searchCallback:CvSearchPaneCallback)=>{
                             const detailsContext:DetailsContext = cvContext.scopeCtx.scopeObj;
                             return (
                                <CvRecord entityRec={record} renderer={(cvContext:CvContext)=>{
                                   return (
                                            <div className="cv-detail-container">
                                                {(()=>{
                                                    const cancelButtonText = detailsContext.detailsDef.cancelButtonText;
                                                    const commitButtonText = detailsContext.detailsDef.commitButtonText;
                                                    return <CvDetailsPanelCommitCancelControls cancelButtonText={cancelButtonText} commitButtonText={commitButtonText}
                                                     onCancel={this._openReadMode.bind(this, searchCallback)} onCommit={this._search.bind(this, searchCallback)}/>
                                                })()}
                                                <table className="table table-striped">
                                                    <tbody>{this._layoutSearchPane(detailsContext, record, searchCallback)}</tbody>
                                                </table>
                                                {(()=>{
                                                    const cancelButtonText = detailsContext.detailsDef.cancelButtonText;
                                                    const commitButtonText = detailsContext.detailsDef.commitButtonText;
                                                    return <CvDetailsPanelCommitCancelControls cancelButtonText={cancelButtonText} commitButtonText={commitButtonText}
                                                     onCancel={this._openReadMode.bind(this, searchCallback)} onCommit={this._search.bind(this, searchCallback)}/>
                                                })()}
                                            </div>
                                    );
                                }}/>
                            );

               }}/>
    },

    _isSectionTitleDef: function (row) {
        return row.every((cellDef:CellDef)=>{ return cellDef.values.every((cellValueDef:CellValueDef)=>{
            return cellValueDef instanceof LabelCellValueDef;
        })});
    },

    _cellCount(rows:Array<Array<CellDef>>):number{
        return rows.reduce((prev, cellDefRow:Array<CellDef>)=>{
            const numCellValueDefs:number = cellDefRow.reduce((prev, cellDef:CellDef)=>{
                return cellDef.values ? prev + cellDef.values.length : prev;
            }, 0);
            return numCellValueDefs > prev ?  numCellValueDefs : prev;
        }, 0);
    },

    _layoutSearchPane: function (detailsContext:DetailsContext, record:EntityRec, searchCallback:CvSearchPaneCallback) {

        const renderedDetailRows = [];
        if(detailsContext) {
            // Weed the tabs out of the rows becausse the dropdown control seems to size itself incorrectly.
            const rows:Array<Array<CellDef>> = detailsContext.detailsDef.rows.map((cellDefRow:Array<CellDef>, index)=> {
                return cellDefRow.filter((cellDef:CellDef)=>{
                    return true
                });
            });
            const maxCellCount = this._cellCount(rows);
            rows.forEach((cellDefRow:Array<CellDef>, index)=> {
                const rowCellCount:number = cellDefRow.reduce((prev, cellDef:CellDef)=>{
                    return cellDef.values ? prev + cellDef.values.length : prev;
                }, 0);
                    renderedDetailRows.push(
                        <CvDataAnno entityRec={record} paneContext={detailsContext} wrapperElem="tr"
                                    wrapperElemProps={{className: "cv-cell-def-row"}} key={index}>
                            {(() => {
                                const renderedRow = cellDefRow.map((cellDef: CellDef, i1: number) => {
                                    return cellDef.values.map((cellValueDef: CellValueDef, i2: number) => {
                                        //Don't show sort properties here
                                        let isTab = cellValueDef instanceof TabCellValueDef;
                                        if (!this._isSortProperty(cellValueDef) && !isTab) {
                                            return <CvCellValueDef detailsContext={detailsContext}
                                                                   detailsCallback={searchCallback}
                                                                   cellValueDef={cellValueDef}
                                                                   wrapperElem="td"
                                                                   wrapperElemProps={{className: 'cv-cell-def-col'}}
                                                                   key={i1 + '_' + i2}/>
                                        }
                                    });
                                });
                                for(let i = 0; i < maxCellCount - rowCellCount; i++) { renderedRow.push([<td/>]); }
                                return renderedRow;
                            })()}
                        </CvDataAnno>
                    );
            });
        }
        return renderedDetailRows;
    },

    _getFilterOperatorCellValueDefForRow: function(cellDefRow:Array<CellDef>) {
        cellDefRow.reduce((prev, cellDef:CellDef)=>{
            return cellDef.values.reduce((prevVal, cellValueDef:CellValueDef)=>{
                return this._isFilterOperatorProperty(cellValueDef) ? cellValueDef : null;
            }, null);
        }, null);
    },

    _isFilterOperatorProperty: function(cellValueDef:CellValueDef):boolean {
        return (cellValueDef instanceof AttributeCellValueDef) &&
            ((cellValueDef as AttributeCellValueDef).propertyName.indexOf(FILTER_OPERATOR_SUFFIX) > -1);
    },

    _isFilterValueProperty: function(cellValueDef:CellValueDef):boolean {
        return (cellValueDef instanceof AttributeCellValueDef) &&
            ((cellValueDef as AttributeCellValueDef).propertyName.indexOf(FILTER_VALUE_SUFFIX) > -1);
    },

    _isSortProperty: function(cellValueDef:CellValueDef):boolean {
        return (cellValueDef instanceof AttributeCellValueDef) &&
            (((cellValueDef as AttributeCellValueDef).propertyName.indexOf(SORT_DIRECTION_SUFFIX) > -1) ||
            ((cellValueDef as AttributeCellValueDef).propertyName.indexOf(SORT_SEQUENCE_SUFFIX) > -1));
    },

    _openReadMode: function(searchCallback:CvSearchPaneCallback) {
        searchCallback.openReadMode((success, error)=>{
        });
    },

    _search: function(searchCallback:CvSearchPaneCallback) {
        searchCallback.submitSearch((success, error)=>{
        });
    }


});
