import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';

import { connect } from 'react-redux';
import { prepareEntity, fetchEntity, saveEntity, deleteEntity, selector, fetchPayments, paymentStatusReportAction, paymentTimelineReportAction } from './redux.js';

import RecurringPaymentItemForm from 'components/RecurringPaymentItemForm';
import { AbstractForm, ActivityIndicator, DetailButtons, DetailTitle, PageSwitcher, SectionHeader, ToolbarButton, Toolbar, ToolbarSection, ToolbarButtons, Alert, Tabs, Tab, ErrorBubble } from 'lib/components';
import Attachments from 'lib/attachment';
import PaymentItems from 'components/PaymentItems';
import { PeriodTitle } from 'containers/Params';
import StatusChart from 'components/StatusChart';
import PaymentTimelineChart from 'components/PaymentTimelineChart';

import Toast from 'components/Toast';
import icons from 'constants/icons';
import { injectIntl } from 'react-intl';
import { settingsSelector } from 'utils/settings';

import PaymentItemForm from 'components/PaymentItemForm';
import ExchangeRateFormFields from 'components/ExchangeRateFormFields';
import PaymentStats from 'components/PaymentStats';
import FetchedContent from 'components/FetchedContent';

import form from 'lib/form';
import validator from 'lib/validator';
import { formatMoney, formatNumber, formatDate } from 'lib/i18n';
import { fromJS } from 'immutable';
import moment from "moment";

import { calculatePaymentStats } from 'utils/calc';

import messages from './messages';
import commonMessages from '../../messages';


const ADD_ONETIME_PAYMENT = "OT";
const ADD_RECURRING_PAYMENT = "R";



function renderButtons(intl, router, cid, disabled) {
    return [
            <ToolbarButton 
                key="rec"
                label={ intl.formatMessage(messages.addRECPayment) } 
                onClick={ () => router.push(`/payments/categories/${cid}/payments/rec/new`) }
                disabled={ disabled }>
                <span className="icon">{ icons.add }</span>
            </ToolbarButton>
            ,
            <ToolbarButton 
                key="ot"
                label={ intl.formatMessage(messages.addOTPayment) } 
                onClick={ () => router.push(`/payments/categories/${cid}/payments/ot/new`) }
                disabled={ disabled }>
                <span className="icon">{ icons.add }</span>
            </ToolbarButton>
        ];
}



class PaymentForm extends AbstractForm {


    renderPayments(intl, payments, cid) {
        if (!payments) {
            return null;
        }

        let { data, paging, sorting, status } = payments;
        let { router, periodParams } = this.props;

        return <div className="pv10">
                    <PaymentItems 
                        items={ data } 
                        onDetailClick={ (pid) => router.push(`/payments/categories/${cid}/payments/${pid}`)} 
                        i18n={ this.props.i18n }
                        disabled={ status == "pending" }
                        />
                    { data ? 
                        <PageSwitcher
                            paging={ paging } 
                            onPageChanged={ (pg) => this.props.fetchPayments(this.props.unitId, cid, periodParams, { ...paging, ...pg, pageSize: 6 }, sorting) } 
                            status={ status } 
                            disabled={ status == "pending" }
                            displayNoPages
                            /> : null 
                    }
            </div>
    }



    render() {
        let { valueOf, i18n, paymentId, invoiceId, attachments, intl, errors, onChangeHandler, disabled, unit, unitId, timelineReport, payments, router } = this.props;

        let currencySymbol = valueOf("currencySymbol", "");
        let fieldProps = {};

        return (
            <div className={ this.props.className }>
                    <Tabs className="mb20">
                        { paymentId ? (
                            <Tab title={ intl.formatMessage(messages.tabOverview) } className="container-max-1200 form p10" titleDecorator={ <ErrorBubble errors={ errors } fields={ ["name", "expenseDate", "totalAmount", "totalPayable"] }/> }>

                                <PeriodTitle changePeriod={ this.props.changePeriod }/>

                                <div className="dashboard-row">
                                    <div className="col-md-6">
                                        <div className="hover-highlight-light mb20 p10">
                                            <h2 className="mb20"></h2>
                                            <DashboardStatusChart />
                                        </div>

                                        <div className="hover-highlight-light mb20 p10">
                                            <h2 className="mb20"></h2>
                                            { timelineReport ? <PaymentTimelineChart { ...timelineReport.data } status={ timelineReport.status } /> : null }
                                        </div>
                                    </div>
                                    <div className="col-md-6 p10">
                                        <FetchedContent 
                                            status={ payments && payments.status } 
                                            error={ payments && payments.error } 
                                            fresh={ payments && payments.fresh } 
                                            empty={ !payments || !payments.data || !payments.data.length } 
                                            buttons={ renderButtons(intl, router, paymentId) }
                                            >
                                            { this.renderPayments.call(this, intl, payments, paymentId) }
                                        </FetchedContent>
                                    </div>
                                </div>
                            </Tab>
                        ) : null }

                        <Tab title={ intl.formatMessage(messages.tabPaymentCategory) } className="container-max-900 form" titleDecorator={ <ErrorBubble errors={ errors } fields={ ["name", "expenseDate", "totalAmount", "totalPayable"] }/> }>
                            <div className="form">
                                <div className="row row-margin-10">
                                    <div className="col-xs-12">
                                        { this.renderField("name", intl.formatMessage(messages.name), { className: "big" }) }
                                    </div>
                                    <div className="col-xs-12">
                                        { this.renderTextArea("note", intl.formatMessage(messages.note)) }
                                    </div>

                                </div>
                            </div>
                        </Tab>
                        <Tab title={ intl.formatMessage(messages.tabCurrency) } className="container-max-900 form" titleDecorator={ <ErrorBubble errors={ errors } fields={ ["name", "expenseDate", "totalAmount", "totalPayable"] }/> }>
                            <ExchangeRateFormFields 
                                form={ this } 
                                fieldProps={ fieldProps } 
                                intl={ intl } 
                                valueOf={ valueOf } 
                                onChangeHandler={ onChangeHandler } 
                                disabled={ disabled } 
                                unitCurrency={ unit.currency } 
                                unitCurrencySymbol={ unit.currencySymbol } 
                                dateField="incomeDate" 
                                />
                        </Tab>
                        { paymentId ? (
                            <Tab title={ intl.formatMessage(messages.tabAttachments) } className="container-max-900 form" titleDecorator={ <ErrorBubble errors={ errors } disabled={ !paymentId } /> }>
                                <Attachments 
                                    unitId={ unitId } 
                                    objectType="paymentCategory" 
                                    objectId={ paymentId }
                                    />
                            </Tab>
                        ) : null }
                    </Tabs>

            </div>
        );
    }

}

PaymentForm = form(injectIntl(PaymentForm), {
    onValidationFailed: Toast.validationFailed,
    validate: (payment, error) => {
        let valid = true;
        if (!validator.required(payment.name)) {
            error({ field: "name", code: "common.validation.requiredField" });
            valid = false;
        }
        if (!validator.required(payment.currency)) {
            error({ field: "currency", code: "common.validation.requiredField" });
            valid = false;
        }
        if (!validator.required(payment.currencySymbol)) {
            error({ field: "currencySymbol", code: "common.validation.requiredField" });
            valid = false;
        }
        return valid;
    }
});






class DashboardStatusChart extends Component {

    render() {
        let { data = {}, status, i18n, intl, unit, className } = this.props;

        return (
            <div className={ className }>
                <div className="hover-highlight-light">
                    <StatusChart 
                        data={ data.data } 
                        currency={ data.currencySymbol || data.currency || unit.currencySymbol || unit.currency } 
                        i18n={ i18n } 
                        /> 
                </div> 
                <ActivityIndicator show={ status === "pending" } type="overlay" size="big" />
            </div>
        );  
    }
}

DashboardStatusChart = connect(settingsSelector((state, props) => state.getIn(["paymentCategoryDetail", "statusReport"]).toJS()), () => ({}) )(DashboardStatusChart);
DashboardStatusChart = injectIntl(DashboardStatusChart);


class PaymentCategoryDetail extends Component {

	constructor(props) {
		super(props);

        this.changePeriod = this.changePeriod.bind(this);

		this.handleBack = this.handleBack.bind(this);
		this.handleDelete = this.handleDelete.bind(this);
		this.handleSave = this.handleSave.bind(this);
	}


	componentWillMount() {
		let id = this.props.params.id;
		let unit = this.props.unit;

		if (id) {
			this.props.fetchEntity(unit.id, id);
			this.props.fetchPayments(unit.id, id);
            this.changePeriod(this.props.periodParams);
		} else {
			this.props.prepareEntity(unit);
		}
	} 


	componentWillReceiveProps(props) {
        let unit = this.props.unit;
		if (props.params.id != this.props.params.id) {
            this.props.fetchEntity(unit.id, id);
            this.changePeriod(this.props.periodParams);
		}
	}

    changePeriod(periodParams) {
        let unitId = this.props.unitId;
        let id = this.props.params.id;
        let { from, to, dateType } = periodParams;

        this.props.paymentStatusReportAction(unitId, id, periodParams);
        this.props.paymentTimelineReportAction(unitId, id, periodParams);
        this.props.fetchPayments(unitId, id, periodParams);
    }


	handleBack() {
		this.context.router.push('/payments');
	}




	async handleSave(data) {
		let id = this.props.params.id;
		let type = this.props.params.mode;
		let unitId = this.props.unitId;
		let intl = this.props.intl;

		try {
			data = await this.props.saveEntity(unitId, data.id, data, { type });
			Toast.saved();
			if (!id) {
				this.context.router.push(`/payments/categories/${data.value.body.id}`);
			}
		} catch (e) {
			Toast.error(e);
		}
	}


    handleDelete() {
        let intl = this.props.intl;
        Alert.alert(
            intl.formatMessage(messages.deleteTitle), 
            intl.formatMessage(messages.deleteQuestion), 
            [
                { text: intl.formatMessage(commonMessages.buttonNo) }, 
                { text: intl.formatMessage(commonMessages.buttonYes), primary: true, onPress: async () => {
                    try {
                        await this.props.deleteEntity(this.props.unitId, this.props.params.paymentId);
                        this.handleBack();
                        Toast.deleted();
                    } catch (e) {
                        Toast.error(e);
                    }
                }
            }]
        );
    }


	render() {
		let 
			intl = this.props.intl,
			id = this.props.params.id,
			payments = this.props.payments,
			status = this.props.status || {},
            timelineReport = this.props.timelineReport || {},
			edit = !!id,
			form = null,
            unit = this.props.unit;

		return (
			<div className="pv10">
                <Toolbar>
                    <ToolbarSection>
                        <DetailTitle 
                            title={ (this.props.status != "pending" && this.props.data && this.props.data.name) || intl.formatMessage(messages.title) }
                            titleIcon={ icons.paymentCategory }
                            />
                    </ToolbarSection>
                    <ToolbarButtons>
                        <ToolbarButton 
                            label={ intl.formatMessage({ id: "common.button.back" }) } 
                            onClick={ this.handleBack }>
                            <span className="icon">{ icons.back }</span>
                        </ToolbarButton>
                        { renderButtons(intl, this.context.router, id, !id) }
                        <ToolbarButton 
                            label={ intl.formatMessage({ id: "common.button.delete" }) } 
                            onClick={ this.handleDelete }
                            disabled={ !edit }>
                            <span className="icon">{ icons.delete }</span>
                        </ToolbarButton>
                        <ToolbarButton 
                            label={ intl.formatMessage({ id: "common.button.save" }) } 
                            onClick={ () => this.refs.detailForm.submit(this.handleSave) }>
                            <span className="icon">{ icons.save }</span>
                        </ToolbarButton>
                    </ToolbarButtons>
                </Toolbar>

				<PaymentForm 
					ref="detailForm" 
					data={ this.props.data } 
					disabled={ status.any } 
					onSubmit={ this.handleSave }
                    unit={ unit } 
                    unitId={ unit.id }
                    paymentId={ id }

                    timelineReport={ timelineReport }
                    payments={ payments }
                    changePeriod={ this.changePeriod }

                    router={ this.context.router }
                    fetchPayments={ this.props.fetchPayments }
                    periodParams={ this.props.periodParams }
					/>

				<ActivityIndicator show={ status.any } type="overlay" />
			</div>
		);
	}

}

PaymentCategoryDetail.contextTypes = {
	router: PropTypes.object.isRequired
};



const mapStateToProps = (state, props) => selector(state);



function mapDispatchToProps(dispatch, props) {
	return {
    	dispatch,
    	prepareEntity: (unit, mode) => dispatch(prepareEntity(unit, mode)),
    	fetchEntity: (unitId, id) => dispatch(fetchEntity(id, { unitId })),
    	fetchPayments: (unitId, id, period, paging, sorting) => dispatch(fetchPayments(unitId, id, period, paging, sorting)),
    	saveEntity: (unitId, id, data) => dispatch(saveEntity(id, data, { unitId })),
    	deleteEntity: (unitId, id) => dispatch(deleteEntity(id, { unitId })),
        paymentStatusReportAction: (unitId, id, params) => dispatch(paymentStatusReportAction(unitId, id, params)),
        paymentTimelineReportAction: (unitId, id, params) => dispatch(paymentTimelineReportAction(unitId, id, params)),
  	};
}


export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(PaymentCategoryDetail));
