/**
 * Created by rburson on 3/18/16.
 */

import * as React from 'react'
import {
    CvActionFiredResult,
    CvState,
    CvProps,
    CvBaseMixin,
    CvContext,
    CvNavigationResult,
    CvDetailsPane,
    CvDetailsPaneCallback,
    CvRecord,
    CvStateChangeResult,
    CvEvent,
    CvValueProvider,
    CvActionHandlerParams,
    CvValueListener,
    CvImagePackageDelete,
    CvImagePackagePick,
    CvImagePackageUndo, CvImageProducer
} from 'catreact'
import {
    CvCellValueDef,
    CvDataAnno,
    CvImageDefaultAddButtonClass,
    CvImageDefaultRemoveButtonClass,
    CvImageDefaultUndoButtonClass
} from './catreact-html'
import {
    FormContext,
    EntityRec,
    DetailsContext,
    CellValueDef,
    CellDef,
    ForcedLineCellValueDef,
    LabelCellValueDef,
    AttributeCellValueDef
} from 'catavolt-sdk'
import {openSignaturePopup} from "./CvSignaturePopup";
import {CvImageDefaultSignatureButtonClass} from "./CvImage";

export interface CvDetailsPanelState extends CvState {
}

/**
 * Details Panel Properties
 */
export interface CvDetailsPanelProps 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>;
}

let FORCED_LINE_DEF:ForcedLineCellValueDef = new ForcedLineCellValueDef();

/**
 * Renders a Details Panel, styled by CSS
 */
export let CvDetailsPanel = React.createClass<CvDetailsPanelProps, CvDetailsPanelState>({

    mixins: [CvBaseMixin],

    render: function () {

        return  <CvDetailsPane {...this.props} detailsRenderer={(cvContext:CvContext,
                             record:EntityRec, detailsCallback:CvDetailsPaneCallback)=>{
                             const detailsContext:DetailsContext = cvContext.scopeCtx.scopeObj;
                             return (
                                <CvRecord entityRec={record} renderer={(cvContext:CvContext)=>{
                                   return (
                                            <div className="cv-component-container cv-detail-container">
                                                {(()=>{
                                                    if(detailsContext.detailsDef.editable) {
                                                        if(detailsContext.isReadMode) {
                                                        return <div className="cv-component-toolbar">
                                                            <CvDetailsPanelControls onRefresh={this._refresh.bind(this, detailsCallback)}
                                                                                    onEdit={this._openWriteMode.bind(this, detailsCallback)}/></div>
                                                        } else if (detailsContext.isWriteMode){
                                                            const cancelButtonText = detailsContext.detailsDef.cancelButtonText;
                                                            const commitButtonText = detailsContext.detailsDef.commitButtonText; 
                                                             return <div className="cv-component-toolbar">
                                                                 <CvDetailsPanelCommitCancelControls cancelButtonText={cancelButtonText}
                                                                                                     commitButtonText={commitButtonText}
                                                                                                     onCancel={this._openReadMode.bind(this, detailsCallback)}
                                                                                                     onCommit={this._save.bind(this, detailsCallback)}/></div>
                                                        }
                                                    } else {
                                                        return null
                                                    }
                                                })()}
                                                <div className="cv-component-body"><div className="cv-component-scroll"><table className="table table-striped">
                                                    <tbody>{this._layoutDetailsPane(detailsContext, record, detailsCallback)}</tbody>
                                                </table></div></div>
                                                {(()=>{
                                                    const cancelButtonText = detailsContext.detailsDef.cancelButtonText;
                                                    const commitButtonText = detailsContext.detailsDef.commitButtonText; 
                                                    return (detailsContext.detailsDef.editable && detailsContext.isWriteMode) ?
                                                        <div className="cv-component-toolbar cv-detail-controls-lower">
                                                            <CvDetailsPanelCommitCancelControls cancelButtonText={cancelButtonText}
                                                                                                commitButtonText={commitButtonText}
                                                                                                onCancel={this._openReadMode.bind(this, detailsCallback)}
                                                                                                onCommit={this._save.bind(this, detailsCallback)}/>
                                                        </div> : null;
                                                })()}
                                            </div>
                                    );
                                }}/>
                            );
                                     
               }}/>
    },
    
    _layoutDetailsPane: function (detailsContext:DetailsContext, record:EntityRec, detailsCallback:CvDetailsPaneCallback) {

        const renderedDetailRows = [];
        if(detailsContext) {
            const outterColumns:number = detailsContext.detailsDef.rows.reduce((prv1, cellDefRow:CellDef[]) => {
                    return Math.max(prv1, cellDefRow.length);
                }, 0);
            detailsContext.detailsDef.rows.forEach((cellDefRow:Array<CellDef>, index)=> {
                    renderedDetailRows.push(
                        <CvDataAnno entityRec={record} paneContext={detailsContext} wrapperElem="tr" wrapperElemProps={{className:"cv-cell-def-row"}} key={index}>
                            {(()=>{
                                return cellDefRow.map((cellDef:CellDef, index:number)=>{  // Each cellDef represents a column
                                    let columnsInThisRow = cellDefRow.length;
                                    let colspan = ((index+1) == columnsInThisRow) ? outterColumns - columnsInThisRow + 1 : 1;
                                    let answer = null;
                                    if (cellDef.values.length <= 1) {
                                        let cellValueDef:CellValueDef = (cellDef.values.length == 1) ? cellDef.values[0] : FORCED_LINE_DEF;
                                        answer = <CvCellValueDef detailsContext={detailsContext} detailsCallback={detailsCallback} cellValueDef={cellValueDef}
                                                                 wrapperElem="td" wrapperElemProps={{className:'cv-cell-def-col', colSpan:colspan}} key={index}
                                                                 imageProducers={this._buildImageProducers(detailsContext, cellValueDef)}/>
                                    } else {
                                        // If there are more than one cellDef.value they should be built in a sub-table to keep the parent column in tact.
                                        answer = <td colSpan={colspan}><table className="table" style={{background: "transparent"}}>
                                            <tr>
                                                {(()=>{
                                                    return cellDef.values.map((cellValueDef:CellValueDef, i2:number)=>{  // These are both labels and attributes
                                                        return <CvCellValueDef detailsContext={detailsContext} detailsCallback={detailsCallback} cellValueDef={cellValueDef}
                                                                               wrapperElem="td" wrapperElemProps={{className:'cv-cell-def-col'}} key={i2}
                                                                               imageProducers={this._buildImageProducers(detailsContext, cellValueDef)}/>
                                                    });

                                                })()}

                                            </tr>
                                        </table></td>
                                    }
                                    return answer;
                                });
                            })()}
                        </CvDataAnno>
                    );
            });
        }
        return renderedDetailRows;
    },

    _buildImageProducers(detailsContext:DetailsContext, cellValueDef:CellValueDef) {
        let imageProducers:Array<CvImageProducer> = null;
        if (!this._isReadModeFor(detailsContext, cellValueDef)) {
            if (cellValueDef instanceof AttributeCellValueDef && detailsContext.isSignature(cellValueDef)) {
                imageProducers = [
                    {
                        prodImageCB: (listener: CvValueListener<Object>)=> {
                            openSignaturePopup(listener);
                        },
                        buttonClassName: CvImageDefaultSignatureButtonClass, includeWhenImageisPresent: true, includeWhenImageIsMissing: true,
                        includeWhenImageIsDeleted: true
                    }
                ];

            } else {
                imageProducers = [
                    {
                        // Pick a new file with the file chooser.
                        prodImageCB: (listener: CvValueListener<Object>) => {
                            listener(new CvImagePackagePick())
                        },
                        buttonClassName: CvImageDefaultAddButtonClass,
                        includeWhenImageisPresent: true,
                        includeWhenImageIsMissing: true,
                        includeWhenImageIsDeleted: true
                    },
                    {
                        // Delete existing image
                        prodImageCB: (listener: CvValueListener<Object>) => {
                            listener(new CvImagePackageDelete())
                        },
                        buttonClassName: CvImageDefaultRemoveButtonClass,
                        includeWhenImageisPresent: true,
                        includeWhenImageIsMissing: false,
                        includeWhenImageIsDeleted: false
                    },
                    {
                        // Undo previous delete image
                        prodImageCB: (listener: CvValueListener<Object>) => {
                            listener(new CvImagePackageUndo())
                        },
                        buttonClassName: CvImageDefaultUndoButtonClass,
                        includeWhenImageisPresent: false,
                        includeWhenImageIsMissing: false,
                        includeWhenImageIsDeleted: true
                    }
                ];
            }
        }
        return imageProducers;
    },
    _isReadModeFor(detailsContext:DetailsContext, cellValueDef:CellValueDef) {
        return cellValueDef instanceof AttributeCellValueDef && detailsContext.isReadModeFor((cellValueDef as AttributeCellValueDef).propertyName);
    },

    _openWriteMode: function(detailsCallback:CvDetailsPaneCallback) {
        detailsCallback.openWriteMode((success, error)=>{
        });
    },

    _openReadMode: function(detailsCallback:CvDetailsPaneCallback) {
        detailsCallback.openReadMode((success, error)=>{
        });
    },
    
    _refresh: function(detailsCallback:CvDetailsPaneCallback) {
        detailsCallback.refresh();
    },
    
    _save: function(detailsCallback:CvDetailsPaneCallback) {
        detailsCallback.saveChanges((success, error)=>{
        });
    }

});

export let CvDetailsPanelCommitCancelControls = React.createClass<{cancelButtonText:string,
    commitButtonText:string, onCancel:()=>{}, onCommit:()=>{}}, {}>({
    
    render: function() {
       
        const {cancelButtonText, commitButtonText, onCancel, onCommit} = this.props;
        
        return <div className="text-right">
            <button className="btn btn-default" onClick={onCancel}>
                {cancelButtonText ? <span style={{marginRight:'10px'}}>{cancelButtonText}</span> : null}
                <span className="glyphicon glyphicon-remove" aria-hidden="true"/>
            </button>
            <button className="btn btn-default" onClick={onCommit}>
                {commitButtonText ? <span style={{marginRight:'10px'}}>{commitButtonText}</span> : null}
                <span className="glyphicon glyphicon-ok" aria-hidden="true"/>
            </button>
        </div>
    }
    
});

export let CvDetailsPanelControls = React.createClass<{onRefresh:()=>{}, onEdit:()=>{}}, {}>({

    render: function() {
        return <div className="text-right">
            <button className="btn btn-default" onClick={this.props.onRefresh}>
                <span className="glyphicon glyphicon-refresh" aria-hidden="true"/>
            </button>
            <button className="btn btn-default" onClick={this.props.onEdit}>
                <span className="glyphicon glyphicon-edit" aria-hidden="true"/>
            </button>
        </div>
    }

});


