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

import * as React from 'react'
import {
    CvState,
    CvWorkbench,
    CvProps,
    CvBaseMixin,
    CvEvent,
    CvNavigationResult,
    CvLauncher,
    CvLaunchActionCallback,
    CvContext,
    CvValueProvider,
    CvActionFiredResult
} from 'catreact'
import {Workbench, AppWinDef, WorkbenchLaunchAction} from 'catavolt-sdk'

export interface CvGraphicalWorkbenchState extends CvState {
    workbench?:Workbench;
}

export interface CvGraphicalWorkbenchProps extends CvProps {
    /**
     * The sdk {AppWinDef} from which to retrieve the workbenches 
     */
    appWinDef?:AppWinDef;
    /**
     * Register to receive {@link CvEvent}s of type {@link CvNavigationResult}
     */
    launchListeners?:Array<(event:CvEvent<CvNavigationResult>)=>void>
    /**
     * Register to receive {@link CvEvent}s of type {@link CvActionFiredResult}
     */
    actionListeners?:Array<(event:CvEvent<CvActionFiredResult>)=>void>
    /**
     * The workbench id of the workbench to show.
     * Should not be used if the workbench property is provided
     */
    workbenchId?:string;
    /**
     * The workbench to show
     * Should not be used if the workbenchId property is provided
     */
    workbench?:Workbench;
    /**
     * Number of columns to use for the workbench launcher display
     */
    numCols?:number;
    /**
     * A workbench selection provider, to which this component will 'listen' and display workbench selection changes
     */
    selectionProvider?:CvValueProvider<Workbench>;
}

/*
 ***************************************************
 * Render a Workbench with Icons
 ***************************************************
 */

export var CvGraphicalWorkbench = React.createClass<CvGraphicalWorkbenchProps, CvGraphicalWorkbenchState>({

    mixins: [CvBaseMixin],

    componentDidMount: function () {
        this.refresh(this.props);
    },

    componentWillReceiveProps: function (nextProps) {
        this.refresh(nextProps);
    },

    appWinDef: function ():AppWinDef {
        return this.props.appWinDef || this.firstInScope(AppWinDef);
    },

    getDefaultProps: function () {
        return {
            appWinDef: null,
            launchListeners: [],
            actionListeners: [],
            numCols: 3,
            selectionProvider: null,
            workbench: null,
            workbenchId: null
        }
    },

    getInitialState: function () {
        return {workbench: null}
    },

    getChildContext: function () {
        const ctx = this.getDefaultChildContext();
        ctx.cvContext.scopeCtx.scopeObj = this.workbench();
        return ctx;
    },

    refresh: function (props:CvGraphicalWorkbenchProps) {

        if (props.workbench) {
            this.setState({workbench: props.workbench});
        } else if (props.workbenchId) {
            const workbench = this._workbenchForId(props.workbenchId);
            if(workbench) {
                this.setState({workbench: workbench});
            } else {
                this.setState({workbench: this.appWinDef().workbenches[0]})
            }
        } else {
            this.setState({workbench: this.appWinDef().workbenches[0]})
        } 
        const selectionProvider:CvValueProvider<Workbench> = props.selectionProvider;
        if (selectionProvider) {
            selectionProvider.subscribe(this._updateWorkbench);
        }

    },


    render: function () {

        const workbench:Workbench = this.workbench();

        if (workbench) {
            return (
                <CvWorkbench workbench={workbench} appWinDef={this.appWinDef()} renderer={(cvContext:CvContext)=>{

                const cssCols = Math.floor(12/this.props.numCols);
                const workbench:Workbench = cvContext.scopeCtx.scopeObj as Workbench;
                const newChildren = [];
                let rowElems = [];
                workbench.workbenchLaunchActions.forEach((launchAction:WorkbenchLaunchAction, i:number) => {
                    rowElems.push(<CvLauncher launchAction={launchAction} key={launchAction.actionId}
                            launchListeners={this.props.launchListeners} actionListeners={this.props.actionListeners}
                            renderer={(cvContext:CvContext, callback:CvLaunchActionCallback)=>{
                                const launcher = cvContext.scopeCtx.scopeObj as WorkbenchLaunchAction;
                                return (
                                    <div onClick={()=>{callback.fireLaunchAction()}}
                                        className={"col-sm-" + cssCols + " cv-launcher-container cv-target animated fadeIn"}
                                        id={launcher.alias || launcher.actionId}>
                                            <img className="cv-launcher-icon img-responsive center-block" src={launcher.iconBase} onError={this._loadPlaceholder}/>
                                            <h4 className="cv-launcher-text small text-center">{launcher.name}</h4>
                                    </div>);
                            }}
                     />);
                    if(i % this.props.numCols == this.props.numCols-1) {
                        newChildren.push(React.createElement('div', {className:'row', key: i}, rowElems));
                        rowElems = [];
                    }
                });
                if(rowElems.length > 0){
                    newChildren.push(React.createElement('div', {className:'row', key: '00'}, rowElems));
                }

                return <div>{newChildren}</div>
                
            }}/>
            );
        } else {
            return null;
        }
    },

    workbench: function () {
        return this.state.workbench;
    },

    _loadPlaceholder: function (e) {
        e.preventDefault();
        e.target.src = 'http://cdn.churchm.ag/wp-content/uploads/2013/06/404-Space-Invaders.png'
    },

    _updateWorkbench: function (workbench:Workbench) {
        this.setState({workbench: workbench});
    },

    _workbenchForId: function(id:string) {
        const appWinDef = this.appWinDef();
        let workbench = null;
        appWinDef.workbenches.some((wb)=> {
            if (wb.workbenchId == id) {
                workbench = wb;
                return true;
            } else {
                return false;
            }
        });
        return workbench;
    }

});

export interface CvGraphicalWorkbenchPanelState extends CvState {
}

export interface CvGraphicalWorkbenchPanelProps extends CvProps {
    /**
     * The sdk {AppWinDef} from which to retrieve the workbenches
     */
    appWinDef?:AppWinDef;
    /**
     * The workbench id of the workbench to show.
     * Should not be used if the workbench property is provided
     */
    workbenchId:string;
    /**
     * Function that renders the given workbench
     */
    workbenchRenderer:(workbench:Workbench)=>{};
}

export var CvGraphicalWorkbenchPanel = React.createClass<CvGraphicalWorkbenchPanelProps, CvGraphicalWorkbenchPanelState>({

    mixins: [CvBaseMixin],

    appWinDef: function ():AppWinDef {
        return this.props.appWinDef || this.firstInScope(AppWinDef);
    },

    getDefaultProps: function() {
        return {appWinDef:null, workbench: null, workbenchId:null, workbenchRenderer: null}
    },

    render: function () { 
       
        const workbench = this.workbench();
        
        if (this.props.renderer) {
          return this.props.renderer(this.getChildContext().cvContext);
        }  else {
            return (<div className="cv-workbench-manager-container animated fadeIn">
                <div className="cv-panel panel panel-primary cv-workbench-panel">
                    <div className="cv-panel-heading panel-heading">
                        <h3 className="cv-panel-title panel-title">{workbench ? workbench.name : ''}</h3>
                    </div>
                    <div className="cv-panel-body cv-workbench-panel-body">
                        <div className="cv-workbench-scroll-container">{this.props.workbenchRenderer(workbench)}</div>
                    </div>
                </div>
            </div>);
        }

    },
    
    workbench: function() {
        if (this.props.workbenchId) {
            const workbench = this._workbenchForId(this.props.workbenchId);
            if(workbench) {
                return workbench;
            } else {
                return this.appWinDef().workbenches.length > 0 ? this.appWinDef().workbenches[0] : null;
            }
        } 
    },

    _workbenchForId: function(id:string) {
        const appWinDef = this.appWinDef();
        let workbench = null;
        appWinDef.workbenches.some((wb)=> {
            if (wb.workbenchId == id) {
                workbench = wb;
                return true;
            } else {
                return false;
            }
        });
        return workbench;
    }

});

