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

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

import Toast from 'components/Toast';

import { AbstractForm, ButtonBar, Button, DetailButtons, ActivityIndicator, DetailTitle, ToolbarButton, Toolbar, ToolbarSection, ToolbarButtons, Alert, Title, Tabs, Tab, ErrorBubble } from 'lib/components';

import { periodCheckDecorator } from 'containers/Params';
import { formatDate } from 'lib/i18n'

import Attachments from 'lib/attachment';
import Tags from 'lib/tag';

import TaxItems from 'components/TaxItems';
import EntityStatus from 'components/EntityStatus';
import ExchangeRateFormFields, { exchangeRateFields, validateExchangeRate } from 'components/ExchangeRateFormFields';

import form from 'lib/form';
import validator from 'lib/validator';

import icons from 'constants/icons';
import backendRequest from 'lib/backend';


import { injectIntl } from 'react-intl';
import messages from './messages.js';
import commonMessages from '../../messages.js';


class ExpenseForm extends AbstractForm {


    render() {
        let { valueOf, onChangeHandler, attachments, intl, disabled, taxTemplates, unitId, edit, className, errors, expenseId, i18n, unit } = this.props;
        let fieldProps = { disabled, i18n };

        return (
            <div className={ className }>
                <Tabs className="mb20">
                    <Tab title={ intl.formatMessage(messages.tabExpense) } className="container-max-900 form" titleDecorator={ <ErrorBubble errors={ errors } fields={ ["name", "expenseDate", "totalAmount", "totalPayable"] }/> }>
                        <div className="row">
                            <div className="col-sm-5">
                                <div className="mb20">
                                    { this.renderField("expenseId", intl.formatMessage(messages.expenseId), { ...fieldProps, className: "big" }) }
                                </div>
                            </div>
                        </div>
                        <div className="row mb30">
                            <div className="col-sm-5">
                                { this.renderField("subjectName", intl.formatMessage(messages.subjectName), fieldProps) }
                                { this.renderField("subjectIdNumber", intl.formatMessage(messages.subjectIdNumber), fieldProps) }
                                { this.renderField("subjectTaxNumber", intl.formatMessage(messages.subjectTaxNumber), fieldProps) }
                            </div>
                            <div className="col-sm-2"/>
                            <div className="col-sm-5">
                                { this.renderDateField("expenseDate", intl.formatMessage(messages.expenseDate), fieldProps) }
                                <EntityStatus
                                    className="pv10"
                                    status={ valueOf("status") }
                                    dueDate={ valueOf("dueDate") }
                                    onStatusChange={ onChangeHandler("status", s => s) }
                                    paymentDate={ valueOf("paymentDate") }
                                    onPaymentDateChange={ onChangeHandler("paymentDate", s => s) }
                                    i18n={ i18n }
                                    />
                            </div>
                        </div>

                        <div className="mb30">
                            { this.renderField("name", intl.formatMessage(messages.name), { ...fieldProps, className: "big" }) }
                            { this.renderTextArea("description", intl.formatMessage(messages.description), fieldProps) }
        
                        </div>

                        <div className="mb30">
                            <div className="row">
                                <div className="col-sm-7"/>
                                <div className="col-sm-5">
                                    { this.renderMoneyField("totalAmount", intl.formatMessage(messages.amount), valueOf("currencySymbol"), valueOf("currency"), {...fieldProps, className: "big" }) }
        
                                    <TaxItems 
                                        className="pv10 mb20 buttons-center"
                                        items={ valueOf('taxItems') }
                                        currencySymbol={ valueOf('currencySymbol', '') }
                                        onChange={ onChangeHandler('taxItems', items => items) }
                                        baseAmount={ valueOf("totalAmount") }
                                        taxTemplates={ taxTemplates }
                                        disabled={ disabled }
                                        />

                                    { this.renderMoneyField("totalPayable", intl.formatMessage(messages.totalPayable), valueOf("currencySymbol"), valueOf("currency"), fieldProps) }
                                </div>
                            </div>

                        </div>
                    </Tab>

                    <Tab title={ intl.formatMessage(messages.tabCurrency) } className="container-max-900 form" titleDecorator={ <ErrorBubble errors={ errors } fields={ exchangeRateFields} /> }>
                        <ExchangeRateFormFields form={ this } fieldProps={ fieldProps } intl={ intl } valueOf={ valueOf } onChangeHandler={ onChangeHandler } disabled={ disabled } unitCurrency={ unit.currency }  unitCurrencySymbol={ unit.currencySymbol } />
                    </Tab>


                    <Tab title={ intl.formatMessage(messages.tabAttachments) } className="container-max-900" disabled={ !expenseId }>
                        { attachments ? ( 
                            <Attachments 
                                className="pv10"
                                unitId={ unitId } 
                                objectType="expense" 
                                objectId={ expenseId }
                                disabled={ disabled || !expenseId }
                                />
                        ) : null }
                    </Tab>
                </Tabs>

            </div>
        );
    }

}


ExpenseForm = form(injectIntl(ExpenseForm), {
    onValidationFailed: Toast.validationFailed,
    validate: (expense, error) => {
        let valid = true;
        if (!validator.required(expense.name)) {
            error({ field: "name", code: "common.validation.requiredField" })
            valid = false;
        }
        if (!validator.required(expense.expenseDate)) {
            error({ field: "expenseDate", code: "common.validation.requiredField" })
            valid = false;
        }
        if (!validator.required(expense.totalAmount)) {
            error({ field: "totalAmount", code: "common.validation.requiredField" })
            valid = false;
        } else if (!validator.decimal(expense.totalAmount)) {
            error({ field: "totalAmount", code: "common.validation.decimalField" })
            valid = false;
        }
        if (!validator.required(expense.totalPayable)) {
            error({ field: "totalPayable", code: "common.validation.requiredField" })
            valid = false;
        } else if (!validator.decimal(expense.totalPayable)) {
            error({ field: "totalPayable", code: "common.validation.decimalField" })
            valid = false;
        }

        if (!validateExchangeRate(expense, error)) {
            valid = false;
        }

        return valid;
    }
});



class ExpenseDetail extends Component {

	constructor(props) {
		super(props);

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


	componentWillMount() {
		let id = this.props.params.expenseId;
		let unitId = this.props.unitId;
		if (id) {
			this.props.fetchEntity(unitId, id);
		} else {
			this.props.prepareEntity(this.props.unit);
		}
	} 


	handleBack() {
        let { onBack, backPath, route } = this.props;
        if (typeof onBack === "function") {
            return onBack();
        }
        if (backPath) {
            return this.context.router.push(backPath);
        }
        if (route && route.backRoute) {
            return this.context.router.push(route.backRoute);
        }
		this.context.router.push('/expenses');
	}


    handleSave(data) {
        let { periodParams, intl, route, i18n } = this.props;
        periodCheckDecorator(async () => {
            let id = this.props.params.expenseId;
            let unitId = this.props.unitId;
            try {
                data = await this.props.saveEntity(unitId, data.id, data);
                Toast.saved();
                if (!id) {
                    if (route && route.successRoute) {
                        this.context.router.push(`${route.successRoute}/${data.value.body.id}`);
                    } else {
                        this.context.router.push(`/expenses/${data.value.body.id}`);
                    }
                }
            } catch (e) {
                Toast.error(e);
            }
        }, {
            periodParams,
            date: data.expenseDate,
            intl,
            i18n
        });
    }

    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.expenseId);
                        this.handleBack();
                        Toast.deleted();
                    } catch (e) {
                        Toast.error(e);
                    }
                }
            }]
        );
    }

    async handleClone() {
        let { unitId, route, intl } = this.props;
        let data = this.refs.detailForm.getData();
        try {
            let response = await backendRequest(`/api/${unitId}/expenses/clone`, "POST", { body: data });

            let expense = response.body;

            if (expense && expense.id) {
                Toast.saved();
                this.context.router.push(`/expenses/${expense.id}`);
                this.props.fetchEntity(unitId, expense.id);
            }
        } catch (e) {
            console.error(e);
            Toast.error(e);
        }
    }

	render() {
		let 
			status = this.props.status,
			pending = !!(status && ( status.isFetching || status.isSaving || status.isDeleting)),
			id = this.props.params.expenseId,
			edit = !!id,
			intl = this.props.intl;
			
		return (
			<div className="pv10">
                <Toolbar>
                    <ToolbarSection>
                        <DetailTitle 
                            title={ (this.props.data && this.props.data.name) || intl.formatMessage(messages.title) }
                            titleIcon={ icons.expenses }
                            />
                    </ToolbarSection>
                     <ToolbarButtons>
                        <ToolbarButton 
                            label={ intl.formatMessage(commonMessages.buttonBack) } 
                            onClick={ this.handleBack }>
                            <span className="icon">{ icons.back }</span>
                        </ToolbarButton>
                        <ToolbarButton 
                            label={ intl.formatMessage(commonMessages.buttonDelete) } 
                            onClick={ this.handleDelete }
                            disabled={ pending || !id }
                            >
                            <span className="icon">{ icons.delete }</span>
                        </ToolbarButton>
                        <ToolbarButton 
                                label={ intl.formatMessage(messages.cloneButton) } 
                                onClick={ this.handleClone }
                                disabled={ pending || !id }
                                >
                                <span className="icon">{ icons.copy }</span>
                        </ToolbarButton>
                        <ToolbarButton 
                            label={ intl.formatMessage(commonMessages.buttonSave) } 
                            onClick={ () => this.refs.detailForm.submit(this.handleSave) }
                            disabled={ pending }
                            >
                            <span className="icon">{ icons.save }</span>
                        </ToolbarButton>
                    </ToolbarButtons>
               </Toolbar>

				<ExpenseForm 
					ref="detailForm"
					data={ this.props.data } 

					onSubmit={ this.handleSave }

					attachments={ edit }
					expenseId={ id }
					unitId={ this.props.unitId }
                    unit={ this.props.unit }

					i18n={ this.props.i18n }
                    taxTemplates={ this.props.unit.taxTemplates }

                    disabled={ pending }/>

				<ActivityIndicator show={ pending } type="overlay" />
			</div>
		);
	}

}

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



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



function mapDispatchToProps(dispatch, props) {
	return {
    	dispatch,
    	prepareEntity: (unit) => dispatch(prepareEntity(unit)),
    	fetchEntity: (unitId, id) => dispatch(fetchEntity(id, { unitId })),
    	saveEntity: (unitId, id, data) => dispatch(saveEntity(id, data, { unitId })),
    	deleteEntity: (unitId, id) => dispatch(deleteEntity(id, { unitId }))
  	};
}


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