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 { download } from 'lib/backend';
import Toast from 'components/Toast';

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

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

import icons from 'constants/icons';

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


import form from 'lib/form';
import validator from 'lib/validator';
import { calculateIncome } from 'utils/calc';

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


class IncomeForm extends AbstractForm {


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

        return (
            <div className={ this.props.className }>
                <Tabs className="mb20">
                    <Tab title={ intl.formatMessage(messages.tabIncome) } className="container-max-900 form" titleDecorator={ <ErrorBubble errors={ errors } fields={ ["name", "expenseDate", "totalAmount", "totalPayable", "paymentDate"] }/> }>
                        <div className="row mb20">
                            <div className="col-sm-5">
                                { this.renderField("incomeId", intl.formatMessage(messages.incomeId), {...fieldProps, className: "big" }) }
                            </div>
                            <div className="col-sm-2"/>
                            <div className="col-sm-5">
                                { this.renderDateField("incomeDate", intl.formatMessage(messages.incomeDate), fieldProps) }
                                <EntityStatus
                                    className="pv10"
                                    status={ valueOf("status") }
                                    dueDate={ valueOf("dueDate") }
                                    onStatusChange={ onChangeHandler("status", s => s) }
                                    paymentDate={ valueOf("paymentDate") }
                                    onPaymentDateChange={ onChangeHandler("paymentDate", s => s) }
                                    errors={ errors }
                                    i18n={ i18n }
                                    />
                            </div>
                        </div>
                        <div className="mb30">
                            { this.renderField("name", intl.formatMessage(messages.name), fieldProps) }
                            { 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.totalAmount), valueOf("currencySymbol"), valueOf("currency"), { ...fieldProps, className: "big" }) }

                                    <TaxItems 
                                        className="mv20"
                                        items={ valueOf('taxItems') }
                                        currencySymbol={ valueOf('currencySymbol', '') }
                                        onChange={ this.props.onChangeHandler('taxItems', items => items, (items, values) => {
                                            //TODO use immutable to prevent to/from JS
                                            let invoice = calculateIncome(values.toJS());
                                            return values.set("totalAmount", invoice.totalAmount).set("totalPayable", invoice.totalPayable);
                                        }) }
                                        disabled={ disabled }
                                        baseAmount={ this.props.valueOf("totalAmount") }
                                        taxTemplates={ taxTemplates }
                                        />
                                </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 } 
                            dateField="incomeDate" 
                            errors={ errors }
                            />
                    </Tab>
                    <Tab title={ intl.formatMessage(messages.tabAttachments) } className="container-max-900 form">
                        <Attachments 
                            unitId={ this.props.unitId } 
                            objectType="income" 
                            objectId={ incomeId }
                            disabled={ disabled || !incomeId }
                            />
                    </Tab>
                </Tabs>
            </div>
        );
    }

}


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

        if (income.status == "PAID" && !validator.required(income.paymentDate)) {
            error({ field: "paymentDate", code: "common.validation.requiredField" })
            valid = false;
        }

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




class IncomeDetail 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.state = {};
    }


    componentWillMount() {
        let id = this.props.params.incomeId;
        if (id) {
            this.props.fetchEntity(this.props.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('/income');
    }


    handleSave(data) {
        let { periodParams, intl, route, i18n } = this.props;
        periodCheckDecorator(async () => {
            let id = this.props.params.incomeId;
            try {
                data = await this.props.saveEntity(this.props.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(`/income/${data.value.body.id}`);
                    }
                }
            } catch (e) {
                Toast.error(e);
            }
        }, {
            periodParams,
            date: data.incomeDate,
            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.incomeId);
                        this.handleBack();
                        Toast.deleted();
                    } catch (e) {
                        Toast.error(e);
                    }
                }
            }]
        );
    }


    render() {
        let id = this.props.params.incomeId;
        let intl = this.props.intl;
        let
            status = this.props.status,
            pending = !!(status && ( status.isFetching || status.isSaving || status.isDeleting)),
            disabled = false;

        return (
            <div className="pv10">
                <Toolbar>
                    <ToolbarSection>
                        <DetailTitle 
                            title={ (this.props.data && this.props.data.name) || intl.formatMessage(messages.title) }
                            titleIcon={ icons.income }
                            />
                    </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(commonMessages.buttonSave) } 
                            onClick={ () => this.refs.form.submit(this.handleSave) }
                            disabled={ pending }>
                            <span className="icon">{ icons.save }</span>
                        </ToolbarButton>
                    </ToolbarButtons>
                </Toolbar>

                <IncomeForm 
                    ref="form"
                    data={ this.props.data } 
                    unit={ this.props.unit }
                    i18n={ this.props.i18n }
                    taxTemplates={ this.props.unit.taxTemplates }             

                    onSubmit={ this.handleSave }

                    incomeId={ id }
                    unitId={ this.props.unitId }   
                    intl={ this.props.intl }

                    disabled={ pending || disabled }
                    />

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

}

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




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(selector, mapDispatchToProps)(IncomeDetail));
