/**
 * Created by rburson on 12/23/15.
 */

import * as React from 'react'
import {
    CvState,
    CvProps,
    CvBaseMixin,
    CvEvent,
    CvEventRegistry,
    CvEventType,
    CvNavigationResult,
    CvResourceManager,
    CvMessage,
    CvMessageType,
    CvNavigationResultUtil
} from './catreact-core'
import {
    NavRequest, NavRequestUtil, Try
} from 'catavolt-sdk'

export interface CvNavigationState extends CvState {
    visible: boolean;
    navRequest:NavRequest;
}

export interface CvNavigationProps extends CvProps {
    /**
     * The result of a navigation.  Should not be used if the navigationId property is provided
     */
    navigationResult?:CvNavigationResult;
    /**
     * The cache identifier of the result of a Navigation. Should not be used if the navigationResult is provided.
     */
    navigationId?:string;
     /**
      * Setting persistent true, allows this component to remain visible, even after another, new Navigation has
      * taken place.  This is useful for single page apps where components may be coresident.
      */
    persistent?: boolean,
    /**
     * Allows for one Navigation component to target another, when coresident on the page.
     */
    targetId?: string,
}


/*
 ***************************************************
 * Render a NavRequest
 ***************************************************
 */
export var CvNavigation = React.createClass<CvNavigationProps, CvNavigationState>({

    mixins: [CvBaseMixin],

    componentDidMount: function () {

        if(this.props.navigationResult) {
            this.setState({navRequest: this.props.navigationResult.navRequest, visible:true});
        } else if(this.props.navigationId){
            this._handleRetrieveNavigation(this.props.navigationId);
        }
        (this.eventRegistry() as CvEventRegistry).subscribe<CvNavigationResult>(this._navListener, CvEventType.NAVIGATION);
    },
    
    componentWillUnmount: function() {
        (this.eventRegistry() as CvEventRegistry).unsubscribe(this._navListener);
    },
    
    componentWillReceiveProps: function(nextProps) {
        if(nextProps.navigationResult) {
            this.setState({navRequest: nextProps.navigationResult.navRequest, visible:true});
        } else if(nextProps.navigationId) {
            this._handleRetrieveNavigation(nextProps.navigationId);
        }
    },

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

    getDefaultProps: function() {
        return {persistent: false, targetId: null, navigationResult: null, navigationId: null};
    },

    getInitialState: function () {
        return {visible: false, navRequest: null}
    },

    render: function () {

        if (this.state.visible && this.state.navRequest) {
            if(this.props.renderer) {
                return this.props.renderer(this.getChildContext().cvContext);
            }else if (React.Children.count(this.props.children) > 0) {
                return this.props.children
            } else {
                return null;
            }
        } else {
            return null;
        }
    },

    _handleRetrieveNavigation: function(navigationId:string) {
        const event:CvEvent<CvNavigationResult> = this.eventRegistry().getEventByKey(navigationId);
        if(!event) {
            const {redirection, actionSource} = CvResourceManager.deserializeRedirection(navigationId);
            NavRequestUtil.fromRedirection(redirection, actionSource,
                this.catavolt().sessionContextTry.success).onComplete((navRequestTry:Try<NavRequest>) => {
                if(navRequestTry.isSuccess) {
                    CvNavigationResultUtil.publishNavigation(this.catavolt(), this.eventRegistry(), navRequestTry.success,
                        (actionSource as any).actionId, (actionSource as any).workbenchId , null, null,
                        false, false);
                    this.setState({navRequest:navRequestTry.success, visible: true});
                }  else {
                    const event:CvEvent<CvMessage> = {type:CvEventType.MESSAGE, eventObj:{message:'Navigation failed',
                        messageObj:navRequestTry.failure, type: CvMessageType.ERROR}}
                    this.eventRegistry().publish(event, false);
                }
            });
        } else {
            this.setState({navRequest:event.eventObj.navRequest, visible: true});
        }

    },

    _navListener: function(navEvent:CvEvent<CvNavigationResult>) {
        const navRequest = navEvent.eventObj.navRequest;
        if (navRequest && this.isMounted()) {
            if (navEvent.eventObj.navTarget) {
                if (this.props.targetId === navEvent.eventObj.navTarget) {
                    this.setState({navRequest: navRequest, visible: true})
                } else {
                    if (!this.props.persistent) this.setState({visible: false});
                }
            }
        }
    },



});
