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

import { connect } from 'react-redux';
import { fetchSummary, fetchCashflow, fetchStatuses, fetchDashboardRecordsAction, selector } from './redux.js';


import { PageTitle, ActivityIndicator, Info, MessagePanel, SummaryPanel, ToolbarButton, Toolbar, ToolbarSection, ToolbarButtons, ToolbarRow, PageSwitcher } from 'lib/components';

//components
import CashflowChart from 'components/CashflowChart';
import StatusChart from 'components/StatusChart';
import CopyrightInfo from 'components/CopyrightInfo';
import FetchedContent, { ErrorInfo } from 'components/FetchedContent';
import { PeriodTitle, getPeriodParams } from 'containers/Params';

//localization
import { injectIntl } from 'react-intl';
import { formatMoney, formatDate } from 'lib/i18n';
import { settingsSelector } from 'utils/settings';

import { Doughnut, HorizontalBar } from 'react-chartjs-2';
import palette from 'utils/palette';
import icons from 'constants/icons';
import messages from './messages.js';

require("./Home.scss");

const handleBillableClick = (type, id, router) => {
    let path = null;

    switch (type) {
        case 'invoice':
            path = `/home/invoices/${id}`;
            break;
        case 'income':
            path = `/home/income/${id}`;
            break;
        case 'expense':
            path = `/home/expenses/${id}`;
            break;
        case 'payment':
            path = `/home/payments/${id}`;
            break;
    }

    if (path) {
        router.push(path);
    }
}


const renderButtons = (router, intl) => {
    return [
        <ToolbarButton key="payment" label={ intl.formatMessage(messages.addPaymentButton) } onClick={ () => handleBillableClick("payment", "new", router) }>
            <span className="icon">{ icons.payment }</span>
        </ToolbarButton>,
        <ToolbarButton key="expense" label={ intl.formatMessage(messages.addExpenseButton) } onClick={ () => handleBillableClick("expense", "new", router) }>
            <span className="icon">{ icons.expense }</span>
        </ToolbarButton>,
        <ToolbarButton key="income" label={ intl.formatMessage(messages.addIncomeButton) } onClick={ () => handleBillableClick("income", "new", router) }>
            <span className="icon">{ icons.income }</span>
        </ToolbarButton>,
        <ToolbarButton key="invoice" label={ intl.formatMessage(messages.addInvoiceButton) } onClick={ () => handleBillableClick("invoice", "new", router) }>
            <span className="icon">{ icons.invoice }</span>
        </ToolbarButton>
    ];
}


//TODO
class DashboardList extends Component {
	render() {
		let { data, fresh, paging, status, i18n, unitId, sorting, from, to, dateType, className, error, onRefresh, intl } = this.props;
		let content = null;
        let { router } = this.context;

        return (
            <FetchedContent 
                status={ status } 
                className={ className } 
                error={ error } 
                fresh={ fresh } 
                empty={ !data || !data.length } 
                size="big"
                buttons={ renderButtons(router, intl) }
                onRefresh={ onRefresh }>

                { Array.isArray(data) ? data.map((row, key) => {
                    let amount = row.type == 'income' || row.type == 'invoice' ? row.amount : row.amount * -1;
                    let amountClassName = "right main-value p5 " + (amount < 0 ? "minus-amount" : "plus-amount");

                    return (
                        <div key={ key } className="flex-list-row">
                            <div className="content">
                                <div className="list-row-data">
                                    <div className="record-type">
                                        <div className="icon">
                                            { icons[row.type] || icons.empty }
                                            <div className={`status-indicator ${row.status || "pending"}`}/>
                                        </div>
                                        <div className="date">{ dateType == "BILLED_DATE" ? formatDate(row.billedDate) : formatDate(row.dueDate) }</div>
                                    </div>
                                    <div className="main">
                                        <div className="main-value">
                                            { row.name }
                                        </div>
                                        <div className="additional-info">
                                            { row.description || " " }
                                        </div>
                                    </div>
                                    <div className={ amountClassName }>
                                        { formatMoney(amount, row.currency, i18n) }
                                    </div>
                                </div>
                            </div>
                            <div className="actions">
                                <button className="icon" onClick={ () => handleBillableClick(row.type, row.objectId, router) }>{icons.leftMenu}</button>
                            </div>
                        </div>
                    );
                }) : null }

                <PageSwitcher
                    paging={ paging } 
                    displayNoPages
                    onPageChanged={ (paging) => this.props.fetchDashboardRecordsAction(unitId, { from, to, dateType }, paging, sorting) } 
                    status={ status } 
                    disabled={ status == "pending" }
                    /> 
            </FetchedContent>
        );
	}
}

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

DashboardList = connect((state, props) => state.getIn(["home", "list"]).toJS(), (dispatch, props) => {
    return {
        dispatch,
        fetchDashboardRecordsAction: (unitId, filter, paging, sorting) => dispatch(fetchDashboardRecordsAction(filter, paging, sorting, { unitId }))
    };
})(DashboardList);
DashboardList = injectIntl(DashboardList);


class DashboardSummary extends Component {

	renderSummaryPanel(status, title, description, content, intl, className) {
		return (
			<div className="col-md-4 p5">
                { status == "failed" ? <div className={ `summary-panel ${className}` }><ErrorInfo size="micro"/></div> : (
    				<SummaryPanel 
    					className={ className }
    					title={ title ? intl.formatMessage(title) : "" } 
    					content={ content }
    					description={ description }
    					pending={ status == "pending" }
    					/>
                ) }                
			</div>
		);
	}

	render() {
		let { data, status, i18n, intl } = this.props;
        if (!data) {
            data = {};
        }
		let currencySymbol = data.currencySymbol || data.currencySymbol || data.currency;

		return (
			<div className="row-flex box-margin-5">
				{ this.renderSummaryPanel(status, messages.incomeTitle, "", formatMoney(data.income, currencySymbol, i18n), intl, "income") }
				{ this.renderSummaryPanel(status, messages.outcomeTitle, "", formatMoney(data.outcome, currencySymbol, i18n), intl, "expenses") }
				{ this.renderSummaryPanel(status, messages.summaryTitle, "", formatMoney(data.balance, currencySymbol, i18n), intl, "balance") }
			</div>
		);	}
}

DashboardSummary = connect(settingsSelector((state, props) => state.getIn(["home", "summary"]).toJS()), (dispatch) => ({}))(DashboardSummary);
DashboardSummary = injectIntl(DashboardSummary);


class DashboardCashflowChart extends Component {

	render() {
		let { currency, currencySymbol, data, labels, status, i18n, intl, unit, error } = this.props;

		return (
            <div className="pv20">
                <div className="p10 hover-highlight-light">
                    <h2 className="mb20">{ intl.formatMessage(messages.cashflowTitle) }</h2>
                    <div className="big-chart">
                        { !error ? <CashflowChart {...i18n} data={ data } labels={ labels } currency={ currencySymbol || currency } /> : null }
                        { error ? <ErrorInfo size="normal"/> : null }
                    </div>
                    <ActivityIndicator show={ status === "pending" } type="overlay" size="big" />
                </div>
            </div>
		);	
    }
}

DashboardCashflowChart = connect((state, props) => state.getIn(["home", "cashflow"]).toJS(), () => ({}) )(DashboardCashflowChart);
DashboardCashflowChart = injectIntl(DashboardCashflowChart);


class DashboardStatusChart extends Component {

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

        let 
            draftLabel = intl.formatMessage(messages.draft),
            activeLabel = intl.formatMessage(messages.active),
            finishedLabel = intl.formatMessage(messages.finished),
            overdueLabel = intl.formatMessage(messages.overdue),

            currency = this.props.currencySymbol || this.props.currency || unit.currencySymbol || unit.currency;

        return (
            <div className="pv20">
                <div className="status-charts">
                    <div className="relative">
                        <h3>{ intl.formatMessage(messages.statusIncome) }</h3>
                        { error ? <ErrorInfo size="normal" onRefresh={ onRefresh } /> : <StatusChart 
                            data={ data && data.income } 
                            currency={ currency } 
                            i18n={ i18n } 
                            draftLabel={ draftLabel }
                            activeLabel={ activeLabel }
                            finishedLabel={ finishedLabel }
                            overdueLabel={ overdueLabel }
                            /> }
                        <ActivityIndicator show={ status === "pending" } type="overlay" size="big" />
                    </div> 
                    <div className="relative">
                        <h3>{ intl.formatMessage(messages.statusOutcome) }</h3>
                        { error ? <ErrorInfo size="normal" onRefresh={ onRefresh } /> : <StatusChart 
                            data={ data && data.outcome } 
                            currency={ currency } 
                            i18n={ i18n } 
                            draftLabel={ draftLabel }
                            activeLabel={ activeLabel }
                            finishedLabel={ finishedLabel }
                            overdueLabel={ overdueLabel }
                            /> }
                        <ActivityIndicator show={ status === "pending" } type="overlay" size="big" />
                    </div> 
                </div>
            </div>
        );  
    }
}

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


class Home extends Component {

	constructor(props) {
		super(props);

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


	colors(summary) {
		return {
			borderColor: summary,
			backgroundColor: summary,
			pointBorderColor: summary,
			pointBackgroundColor: summary,
			pointHoverBackgroundColor: summary,
			pointHoverBorderColor: summary,
		};
	}

	componentWillMount() {
        this.init();
	}

    init() {
        const { list } = this.props;
        this.changePeriod(this.props.periodParams, list && list.paging);
    }

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

		this.props.fetchSummary(unitId, from, to, dateType);
		this.props.fetchCashflow(unitId, from, to, dateType);
		this.props.fetchStatuses(unitId, from, to, dateType);

        this.props.fetchDashboardRecordsAction(unitId, { from, to, dateType }, paging, sorting);
	}


	render() {
		let { intl, i18n, periodParams = {}, unitId } = this.props;
        let { from, to, dateType } = periodParams;
        let { router } = this.context;

		return (
            <div>
            	{/* top section */}
            	<div className="dashboard-row">
            		<div className="col-xs-12 p10">
                        <Toolbar>
                            <ToolbarSection>
                                <PageTitle title={ intl.formatMessage(messages.pageTitle) } titleIcon={ icons.home } />
                            </ToolbarSection>
                            <ToolbarButtons>
                                { renderButtons(router, intl) }
                            </ToolbarButtons>
                            <ToolbarRow>
                                <PeriodTitle changePeriod={ this.changePeriod } />
                            </ToolbarRow>
                        </Toolbar>
            		</div>
            	</div>
            	<div className="dashboard-row">
            		<div className="col-md-6">
            			<div className="p10 min-height-120">
            				<DashboardList unitId={ unitId } from={ from } to={ to } dateType={ dateType }  i18n={ i18n } onRefresh={ this.init } />
            			</div>
            		</div>
            		<div className="col-md-6 p10">
            			<DashboardSummary i18n={ i18n } onRefresh={ this.init }/>
                        <DashboardCashflowChart i18n={ i18n } onRefresh={ this.init }/>
                        <DashboardStatusChart i18n={ i18n } onRefresh={ this.init }/>
            		</div>
            	</div>

	            <CopyrightInfo version={ global.cfg.version }/>
			</div>
		);
	}

}

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



function mapDispatchToProps(dispatch, props) {
	return {
    	fetchSummary: (unitId, from, to, dateType) => dispatch(fetchSummary(unitId, from, to, dateType)),
    	fetchCashflow: (unitId, from, to, dateType) => dispatch(fetchCashflow(unitId, from, to, dateType)),
    	fetchStatuses: (unitId, from, to, dateType) => dispatch(fetchStatuses(unitId, from, to, dateType)),
        fetchDashboardRecordsAction: (unitId, filter, paging, sorting) => dispatch(fetchDashboardRecordsAction(filter, {...paging, pageSize: 7}, sorting, { unitId }))
  	};
}


export default injectIntl(connect(selector, mapDispatchToProps)(Home));
