import { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';

// actions
import {
    learningPlanRequestGet,
    learningPlanRequestCreate,
    learningPlanRequestUpdate,
    learningPlanRequestDelete

} from 'trc-client-core/src/learningPlan/LearningPlanActions.js';


import { requestCourseList } from 'trc-client-core/src/course/CourseActions';
import { jobPositionRequest } from 'trc-client-core/src/participant/ParticipantActions';

import {
    LEARNING_PLAN_GET_FETCH,
    LEARNING_PLAN_GET_ERROR,
    LEARNING_PLAN_CREATE_FETCH,
    LEARNING_PLAN_CREATE_ERROR,
    LEARNING_PLAN_UPDATE_FETCH,
    LEARNING_PLAN_UPDATE_ERROR,
    LEARNING_PLAN_DELETE_FETCH,
    LEARNING_PLAN_DELETE_ERROR

} from 'trc-client-core/src/constants/ActionTypes';


// components
import Page from 'trc-client-core/src/components/Page';
import Loader from 'trc-client-core/src/components/Loader';
import ErrorMessage from 'trc-client-core/src/components/ErrorMessage';
import AutoRequest from 'trc-client-core/src/components/AutoRequest';
import Button from 'bd-stampy/components/Button';

import ModalManager from 'trc-client-core/src/Modal/ModalManager';
import ModalConfirm from 'trc-client-core/src/Modal/ModalConfirm';
import LoadingActions from 'trc-client-core/src/global/LoadingActions';
import AdminLearningPlanForm from 'trc-client-core/src/admin/AdminLearningPlanForm';

//
// AdminLearningPlanEditView class
//

class AdminLearningPlanEditView extends Component {

    //
    // lifecycle methods
    //

    initialState() {
        return {
            created: false,
            copied: false,
            deleted: false,
            saveError: false
        };
    }

    constructor(props) {
        super(props);
        this.state = this.initialState();
    }

    componentWillMount() {
        this.props.dispatch(jobPositionRequest());
        this.props.dispatch(requestCourseList());
    }

    componentWillReceiveProps(newProps) {

        // reset state if a new learning plan's info is to be shown in the form
        if(this.loadsFromExisting(newProps)) {
            this.setState(this.initialState());
        }
    }

    //
    // helpers
    //

    currentLearningPlan() {
        // gets the current learning plan object (an immutable map), or null if none correspond to current learningPlanId prop
        return this.props.learningPlans.get(this.props.params.learningPlanId);
    }

    loadsFromExisting(props = this.props) {
        // returns true if the form loads from an existing record, false if the form starts blank
        return !!props.params.learningPlanId; // true if a learningPlanId exists
    }

    savesToExisting(props = this.props) {
        // returns true if the form saves to an existing record, false if the form is to create a new record on save
        return !!props.route.savesToExisting; // true if savesToExisting is true on the route
    }

    copiesExisting(props = this.props) {
        return this.loadsFromExisting() && !this.savesToExisting();
    }

    getInitialFormValues(currentLearningPlan) {
        if(!currentLearningPlan) {
            return {
                brand: "Toyota"
            };
        }

        var plan = currentLearningPlan.toJS();
        return plan;
    }

    //
    // event and click handlers
    //

    handleSubmit(values, dispatch) {
        this.saveLearningPlan(values);
    }

    handleResetClick(resetForm) {
        ModalManager.showModal(ModalConfirm, {
            title: 'Are you sure you want to reset?',
            message: 'Are you sure you want to reset? Any changes since your last save will be lost.',
            yes: 'Yes I\'m sure',
            onYes: resetForm,
            no: 'Cancel'
        });
    }

    handleCloseClick(ee, dirty = false) {
        ee.preventDefault();
        if(dirty) {
            ModalManager.showModal(ModalConfirm, {
                title: 'Unsaved changes',
                message: 'You may have unsaved changes, are you sure you want to leave this page?',
                yes: 'Leave page',
                onYes: this.closeLearningPlan.bind(this),
                no: 'Cancel'
            });
        } else {
            this.closeLearningPlan();
        }
    }

    handleDeleteClick(ee) {
        ee.preventDefault();
        ModalManager.showModal(ModalConfirm, {
            title: 'Delete learning plan',
            message: 'Are you sure you want to delete this? This action cannot be undone',
            yes: 'Yes I\'m sure',
            onYes: this.deleteLearningPlan.bind(this),
            no: 'Cancel'
        });
    }

    //
    // form actions
    //

    closeLearningPlan() {
        this.props.history.push('/admin/learning-plans');
    }

    saveLearningPlan(learningPlanObject) {
        const { learningPlanId } = this.props.params;

        if(this.copiesExisting()) {
            this.props.dispatch(learningPlanRequestUpdate(learningPlanId,learningPlanObject)).then(
                (data) => {
                    this.setState({
                        copied: data.payload.careerPlanId
                    });
                }
            );

        } else if(this.savesToExisting()) {

            LoadingActions.startLoading();
            this.props.dispatch(learningPlanRequestUpdate(learningPlanId,learningPlanObject)).then(
                (data) => {
                    if(data.type == LEARNING_PLAN_UPDATE_ERROR) {
                        LoadingActions.flashMessage('failure long', 'An error occurred. Your work is not yet saved.\n'+data.payload.message, 5000);
                    } else {
                        LoadingActions.flashMessage('success', 'Save complete');
                    }
                }
            );

        } else {
            this.props.dispatch(learningPlanRequestCreate(learningPlanObject)).then(
                (data) => {
                    this.setState({
                        created: data.payload.careerPlanId
                    });
                }
            );
        }
    }

    deleteLearningPlan() {
        const { learningPlanId } = this.props.params;
        LoadingActions.startLoading();
        this.props.dispatch(learningPlanRequestDelete(learningPlanId)).then(
            (data) => {
                if(data.type == LEARNING_PLAN_DELETE_ERROR) {
                    LoadingActions.flashMessage('failure long', 'An error occurred. This learning plan is not yet deleted.\n'+data.payload.message, 5000);
                } else {
                    LoadingActions.clearAll();
                    this.setState({
                        deleted: true
                    });
                }
            }
        );
    }

    //
    // render
    //

    render() {
        return (
            <Page title="Learning Plan Editor">
                <div>
                    {this.renderEditor()}
                </div>
            </Page>
        );
    }

    renderEditor() {

        const { params: { learningPlanId }, fetching, saving, deleting, error, handleSubmit, courses, jobPositions } = this.props;
        const { created, copied, deleted } = this.state;
        var showErrorPage = false;

        if(fetching) {
            return <Loader />;

        } else if(error) {
            // if there's an error we'll usually want to show an error page, except if the error happens on save
            showErrorPage = true;

        } else if (created) {
            return (
                <div>
                    <h2 className="hug-top">Learning plan created</h2>
                    <p><Button onClick={this.handleCloseClick.bind(this)}>Back to list</Button>&nbsp;<Link to={`/admin/learning-plans/${created}/edit`} activeClassName="is-active" className="Button Button-edit">Edit learning plan</Link></p>
                </div>
            );

        } else if (copied) {
            return (
                <div>
                    <h2 className="hug-top">Learning plan copied</h2>
                    <p><Button onClick={this.handleCloseClick.bind(this)}>Back to list</Button>&nbsp;<Link to={`/admin/learning-plans/${copied}/edit`} activeClassName="is-active" className="Button Button-edit">Edit learning plan</Link></p>
                </div>
            );

        } else if(deleted) {
            return (
                <div>
                    <h2 className="hug-top">Learning plan deleted</h2>
                    <p><Button onClick={this.handleCloseClick.bind(this)}>Back to list</Button></p>
                </div>
            );
        }

        var title, id, plan;

        // if trying to display a learning plan, get learning plan details

        if(learningPlanId) {
            plan = this.currentLearningPlan();

            if(!plan) {
                // learning plan at this URL doesn't exist
                return (
                    <div>
                        <h2 className="hug-top">No learning plan found at this URL</h2>
                        <p><Button onClick={this.handleCloseClick.bind(this)}>Back to list</Button></p>
                    </div>
                );
            }

            var planJS = plan.toJS();
            title = planJS.displayName || "Unnamed learning plan";
            id = planJS.careerPlanId;
            showErrorPage = false;

        } else {
            // no learning plan id means this must be a new one
            title = "New learning plan";
        }

        if(this.copiesExisting()) {
            title = "New copy of " + title;
        }

        if(showErrorPage) {
            return <ErrorMessage code={400} message={error.message} />;
        }

        var initialValues = this.getInitialFormValues(plan);

        return (
            <div>
                <h1 className="hug-top">{title}</h1>

                <AdminLearningPlanForm
                    onSubmit={this.handleSubmit}
                    savesToExisting={this.savesToExisting()}
                    copiesExisting={this.copiesExisting()}
                    isSaving={saving}
                    isDeleting={deleting}
                    onCloseClick={this.handleCloseClick.bind(this)}
                    onDeleteClick={this.handleDeleteClick.bind(this)}
                    onResetClick={this.handleResetClick.bind(this)}
                    onSubmitForm={this.handleSubmit.bind(this)}
                    initialValues={initialValues}
                    courses={courses}
                    jobPositions={jobPositions} />
            </div>
        );
    }
}

AdminLearningPlanEditView.propTypes = {
    learningPlanEdit: PropTypes.object,
    fetching: PropTypes.bool,
    saving: PropTypes.bool,
    deleting: PropTypes.bool,
    error: PropTypes.object
};

const autoRequest = AutoRequest(['params.learningPlanId'], (props) => {

    // get learning plan info
    if(props.params.learningPlanId) {
        props.dispatch(learningPlanRequestGet(props.params.learningPlanId));
    }
});

const connectWithAdminLearningPlan = connect(
    (state) => ({
        learningPlans:  state.learningPlan.get('collection'),
        fetching:       state.async.get( LEARNING_PLAN_GET_FETCH ),
        saving:         state.async.get( LEARNING_PLAN_CREATE_FETCH )
                        || state.async.get( LEARNING_PLAN_UPDATE_FETCH ),
        deleting:       state.async.get( LEARNING_PLAN_DELETE_FETCH ),
        error:          state.async.get( LEARNING_PLAN_GET_ERROR )
                        || state.async.get( LEARNING_PLAN_CREATE_ERROR )
                        || state.async.get( LEARNING_PLAN_UPDATE_ERROR )
                        || state.async.get( LEARNING_PLAN_DELETE_ERROR ),
        courses:        state.course.get('collection'),
        jobPositions:   state.participant.get('jobPositions').toJS()
    })
);

export default connectWithAdminLearningPlan(autoRequest(AdminLearningPlanEditView));
