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

import * as React from 'react'
import { DialogException } from 'catavolt-sdk'
import {
    CvState, CvProps, CvBaseMixin, CvEvent, CvLoginResult, CvLogin, CvContext, CvLoginCallback,
    CvResultCallback, CvActionFiredResult, CvValueAdapter, CvValueProvider, CvValueListener
} from 'catreact'
import {openPopupPrompt} from "./CvPopupPrompt";


export interface CvLoginPanelState extends CvState {
    clientType: string;
    directUrl: string;
    gatewayUrl: string;
    password: string;
    newPassword: string;
    newPassword2: string;
    tenantId: string;
    userId: string;
    error:any;
    passwordExpired: boolean;
    focusOnPassword: boolean;
}

export interface CvLoginPanelProps extends CvProps {
    loginListeners?: Array<(loginEvent:CvEvent<CvLoginResult>)=>void>
    actionListeners?:Array<(event:CvEvent<CvActionFiredResult>)=>void>;
    defaultClientType?: string;
    defaultDirectUrl?: string;
    defaultGatewayUrl?: string;
    defaultPassword?: string;
    defaultTenantId?: string;
    defaultUserId?: string;
    showClientType?: boolean;
    showDirectUrl?: boolean;
    showGatewayUrl?: boolean;
    showTenantId?: boolean;
}

/*
 ***************************************************
 * Render a LoginPanel
 ***************************************************
 */
export var CvLoginPanel = React.createClass<CvLoginPanelProps, CvLoginPanelState>({

    mixins: [CvBaseMixin],

    getChildContext: function () {
        return this.getDefaultChildContext();
    },

    getDefaultProps: function () {
        return {
            loginListeners: [],
            actionListeners: [],
            defaultClientType: 'RICH_CLIENT',
            defaultDirectUrl: '',
            defaultGatewayUrl: 'www.catavolt.net',
            defaultPassword: '',
            defaultNewPassword: '',
            defaultNewPassword2: '',
            defaultTenantId: '',
            defaultUserId: '',
            showClientType: true,
            showDirectUrl: true,
            showGatewayUrl: true,
            showTenantId: true
        }
    },

    getInitialState: function () {
        return {
            directUrl: this.props.defaultDirectUrl,
            tenantId: this.props.defaultTenantId,
            gatewayUrl: this.props.defaultGatewayUrl,
            userId: this.props.defaultUserId,
            password: this.props.defaultPassword,
            newPassword: this.props.defaultNewPassword,
            newPassword2: this.props.defaultNewPassword2,
            clientType: this.props.defaultClientType,
            error:null,
            passwordExpired:false,
            focusOnPassword: false
        }
    },

    render: function () {
            return (
                <CvLogin loginListeners={this.props.loginListeners} actionListeners={this.props.actionListeners}
                         renderer={(cvContext:CvContext, callback:CvLoginCallback)=>{
                    let answer = null;
                    if(!callback.isLoggedIn()) {
                        if (this.state.passwordExpired) {
                            answer = this.promptForChangePassword(callback);
                        } else {
                            answer = this.promptForLogon(callback);
                        }
                    }
                    return answer;
                }}/>
            );
    },

    handleChange: function (field:string, e:any) {
        let nextState = {};
        nextState[field] = e.target.value;
        nextState["focusOnPassword"] = false;
        this.setState(nextState);
    },

    handleRadioChange: function (field, value, e:any) {
        let nextState = {};
        nextState[field] = value;
        this.setState(nextState);
    },

    handleSubmit: function (callback:CvLoginCallback, e:any) {
        e.preventDefault();
        this.setState({error:null});
        const resultCallback:CvResultCallback<CvLoginResult> = (success:CvLoginResult, error:any)=>{
            if(error) {
                let nextState = {error: error};
                if (error instanceof DialogException && (error as DialogException).name == "com.dgoi.core.security.PasswordExpiredException") {
                    let cont = ()=>{ this.setState({passwordExpired: true, focusOnPassword: true, password: ''}) };
                    let cancel = ()=>{ /* do nothing */ };
                    openPopupPrompt("Password Expired", "Your password has expired.  Would you like to change your password now?" ,
                        ["Change Password Now", "Cancel"], [cont, cancel]);
                    ;
                } else {
                    this.setState({error: error});
                }

            }
        };
        if(this.state.passwordExpired) {
            if (this.state.newPassword != this.state.newPassword2) {
                this.setState({error: "Your new password is not the same in the two fields."});
            } else {
                let host = this.state.directUrl ? this.state.directUrl : this.state.gatewayUrl;
                callback.changePasswordAndLogin(host, this.state.tenantId, this.state.clientType,
                    this.state.userId, this.state.password, this.state.newPassword, resultCallback);
            }
        } else if(this.state.directUrl) {
            callback.loginDirectly(this.state.directUrl, this.state.tenantId, this.state.clientType,
                this.state.userId, this.state.password, resultCallback);
        } else {
            callback.login(this.state.gatewayUrl, this.state.tenantId, this.state.clientType,
                this.state.userId, this.state.password, resultCallback);
        }
    },

    promptForChangePassword: function(callback:CvLoginCallback) {
        return <div className="well cv-changepassword-form-container animated fadeInUp">
            <form className="form-horizontal cv-changepassword-form" onSubmit={this.handleSubmit.bind(this, callback)} >
                {(()=>{
                    return this.buildHiddenPromptFields();
                })()}
                <div className="form-group">
                    <label htmlFor="userId" className="col-sm-5 control-label">User Id:</label>
                    <div className="col-sm-7">
                        <input id="userId" type="text" className="form-control"
                               value={this.state.userId}
                               onChange={this.handleChange.bind(this, 'userId')}
                               required/>
                    </div>
                </div>
                <div className="form-group">
                    <label htmlFor="originalPassword" className="col-sm-5 control-label">Original password:</label>
                    <div className="col-sm-7">
                        <input id="originalPassword" type="password" className="form-control"
                               ref={input => this.state.focusOnPassword && input && input.focus()}
                               value={this.state.password}
                               onChange={this.handleChange.bind(this, 'password')}
                               required/>
                    </div>
                </div>
                <div className="form-group">
                    <label htmlFor="newPassword" className="col-sm-5 control-label">New password:</label>
                    <div className="col-sm-7">
                        <input id="newPassword" type="password" className="form-control"
                               value={this.state.newPassword}
                               onChange={this.handleChange.bind(this, 'newPassword')}
                               required/>
                    </div>
                </div>
                <div className="form-group">
                    <label htmlFor="newPassword2" className="col-sm-5 control-label">Repeat new password:</label>
                    <div className="col-sm-7">
                        <input id="newPassword2" type="password" className="form-control"
                               value={this.state.newPassword2}
                               onChange={this.handleChange.bind(this, 'newPassword2')}
                               required/>
                    </div>
                </div>
                {(()=>{ if(this.props.showClientType) {
                    return (<div className="form-group">
                        <label htmlFor="clientType" className="col-sm-5 control-label">Client Type:</label>
                        <div className="col-sm-7">
                            <label className="radio-inline">
                                <input id="clientType" type="radio"
                                       onChange={this.handleRadioChange.bind(this, 'clientType', 'LIMITED_ACCESS')}
                                       checked={this.state.clientType === 'LIMITED_ACCESS'}/>Limited
                            </label>
                            <label className="radio-inline">
                                <input id="clientType" type="radio"
                                       onChange={this.handleRadioChange.bind(this, 'clientType', 'RICH_CLIENT')}
                                       checked={this.state.clientType === 'RICH_CLIENT'}/>Rich
                            </label>
                        </div>
                    </div>)
                }})()}
                <div className="form-group" >
                        <table className="cv-changepassword-buttons">
                            <tr>
                                <td className="col-sm-8 col-sm-offset-2">
                                    <button type="submit" className="btn btn-default btn-primary btn-block"
                                            value="Change">
                                        Change Password <span className="glyphicon glyphicon-ok" />
                                    </button>
                                </td>
                                <td className="col-sm-4 col-sm-offset-2">
                                    <button type="cancel" className="btn btn-primary btn-block"
                                            value="Cancel" onClick={()=>{this.setState({passwordExpired: false});}}>
                                        Cancel <span className="glyphicon glyphicon-remove" />
                                    </button>
                                </td>
                            </tr>
                        </table>
                </div>
                <div>
                    <div className="cv-login-error">
                        {this.state.error ?
                            <div>
                                <span className="glyphicon glyphicon-warning-sign" />
                                <span style={{marginLeft:'10px'}}>{typeof this.state.error === 'string' ? this.state.error : 'Invalid Login'}</span>
                            </div> : null}
                    </div>
                </div>
            </form>
        </div>

    },

    promptForLogon: function(callback:CvLoginCallback) {
        return <div className="well cv-login-form-container animated fadeInUp">
            <form className="form-horizontal cv-login-form" onSubmit={this.handleSubmit.bind(this, callback)}>
                {(()=>{
                    return this.buildHiddenPromptFields();
                })()}
                <div className="form-group">
                    <label htmlFor="userId" className="col-sm-5 control-label">User Id:</label>
                    <div className="col-sm-7">
                        <input id="userId" type="text" className="form-control"
                               value={this.state.userId}
                               onChange={this.handleChange.bind(this, 'userId')}
                               required/>
                    </div>
                </div>
                <div className="form-group">
                    <label htmlFor="password" className="col-sm-5 control-label">Password:</label>
                    <div className="col-sm-7">
                        <input id="password" type="password" className="form-control"
                               value={this.state.password}
                               onChange={this.handleChange.bind(this, 'password')}
                               required/>
                    </div>
                </div>
                {(()=>{ if(this.props.showClientType) {
                    return (<div className="form-group">
                        <label htmlFor="clientType" className="col-sm-5 control-label">Client Type:</label>
                        <div className="col-sm-7">
                            <label className="radio-inline">
                                <input id="clientType" type="radio"
                                       onChange={this.handleRadioChange.bind(this, 'clientType', 'LIMITED_ACCESS')}
                                       checked={this.state.clientType === 'LIMITED_ACCESS'}/>Limited
                            </label>
                            <label className="radio-inline">
                                <input id="clientType" type="radio"
                                       onChange={this.handleRadioChange.bind(this, 'clientType', 'RICH_CLIENT')}
                                       checked={this.state.clientType === 'RICH_CLIENT'}/>Rich
                            </label>
                        </div>
                    </div>)
                }})()}
                <div className="form-group">
                    <div className="col-sm-10 col-sm-offset-2">
                        <button type="submit" className="btn btn-default btn-primary btn-block"
                                value="Login">
                            Login <span className="glyphicon glyphicon-log-in" />
                        </button>
                    </div>
                </div>
                <div>
                    <div className="cv-login-error">
                        {this.state.error ?
                            <div>
                                <span className="glyphicon glyphicon-warning-sign" />
                                <span style={{marginLeft:'10px'}}>Invalid Login</span>
                            </div> : null}
                    </div>
                </div>
            </form>
        </div>
    },

    buildHiddenPromptFields: function() {
        let answer = [];
        if(this.props.showDirectUrl) {
            answer.push(<div className="form-group">
                <label htmlFor="directUrl" className="col-sm-5 control-label">Direct URL:</label>
                <div className="col-sm-7">
                    <input id="directUrl" type="text" className="form-control"
                           value={this.state.directUrl}
                           disabled={!!this.state.gatewayUrl}
                           onChange={this.handleChange.bind(this, 'directUrl')}/>
                </div>
            </div>);
        }
        if(this.props.showGatewayUrl) {
            answer.push(<div className="form-group">
                <label htmlFor="gatewayUrl" className="col-sm-5 control-label">Gateway URL:</label>
                <div className="col-sm-7">
                    <div className="input-group">
                        <input id="gatewayUrl" type="text" className="form-control"
                               value={this.state.gatewayUrl}
                               onChange={this.handleChange.bind(this, 'gatewayUrl')}
                               disabled={!!this.state.directUrl}
                               aria-describedby="http-addon"/>
                    </div>
                </div>
            </div>);
        }
        if(this.props.showTenantId) {
            answer.push(<div className="form-group">
                <label htmlFor="tenantId" className="col-sm-5 control-label">Tenant Id:</label>
                <div className="col-sm-7">
                    <input id="tenantId" type="text" className="form-control"
                           value={this.state.tenantId}
                           onChange={this.handleChange.bind(this, 'tenantId')}
                           required/>
                </div>
            </div>);
        }
        return answer;
    }


});

