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

import { connect } from 'react-redux';
import { fetchList, selector, expenseReportAction, fetchSuppliers, fetchSummary, fetchTimeline } from './redux.js';


//components
import ExpenseList from 'components/ExpenseList';
import FetchedContent from 'components/FetchedContent';
import { ActivityIndicator, Button, ButtonBar, PageSwitcher, ListMessagePanel, ListTitle, SectionHeader, ToolbarButton, Toolbar, ToolbarSection, ToolbarButtons, ToolbarRow, LabeledValue } from 'lib/components';

import { PeriodTitle } from 'containers/Params';
import { injectIntl } from 'react-intl';
import { formatMoney, formatDate, formatPercent, formatNumber } from 'lib/i18n';
import { settingsSelector } from 'utils/settings';

import { Bar, Doughnut, HorizontalBar } from 'react-chartjs-2'
import DoughnutChartLegend from 'components/DoughnutChartLegend';
import palette from 'utils/palette';
import icons from 'constants/icons';

import messages from './messages.js';


const color = (summary) => {
    return {
        borderColor: summary,
        backgroundColor: summary,
        pointBorderColor: summary,
        pointBackgroundColor: summary,
        pointHoverBackgroundColor: summary,
        pointHoverBorderColor: summary,
    };
};

const ExpenseTimelineChart = injectIntl((props) => {
    const { 
        status, 
        unitId, 
        suppliers,
        dates,
        i18n,
        currencySymbol, 
        currency,
        currencyFormat,
        intl
        } = props;

    //TODO detect whether is empty?
    if (!suppliers || !Array.isArray(suppliers)) {
        return null;
    }

    let colors = palette(global._chartColors, suppliers.length);
    let labels = dates.slice();
    for (let i = 0; i < labels.length; i++) {
        labels[i] = formatDate(labels[i], i18n);
    }

    const chart = {
        labels,
        datasets: []
    };

    for (let i = 0; i < suppliers.length; i++) {
        let cd = suppliers[i];
        chart.datasets.push({
            label: cd.name,
            data: cd.data,
            ...color(colors[i])
        });
    }

    let options = {
        responsive: true,
        animation: false,
        maintainAspectRatio: false,
        barValueSpacing: 10,
        tooltips: {
            callbacks: {
                label: (tooltipItem, data) => formatMoney(tooltipItem.yLabel, currencySymbol || currency, i18n)
            }
        },
        elements: {
            line: {
                    fill: false
            }
        },
        legend: {
            display: false 
        },
        scales: {
            xAxes: [
              {
                display: true,
                gridLines: {
                  display: true
                },
                labels: {
                  show: true
                },
                gridLines: {
                    offsetGridLines: true
                }
              }
            ],
            yAxes: [
              {
                type: 'linear',
                display: true,
                position: 'left',
                gridLines: {
                  display: true
                },
                labels: {
                  show: true
                },
                ticks: {
                    beginAtZero: false,
                    scaleBeginAtZero: true,
                    callback: (label, index, labels) => formatNumber(label, i18n)
                }
              }
            ]
        }
    };

    return (
        <div className="customer-timeline-chart">
            <Bar data={ chart } options={ options } height={ 300 } redraw={ true } />
        </div>
    );

});


class ExpensesSummary extends Component {


    render() {
        let { data, status, i18n, intl, unit } = this.props;
        let { currencySymbol, currency, title, description, pending } = data || {};

        let 
            totalLabel = intl.formatMessage(messages.summaryTotal),
            averageAmount = intl.formatMessage(messages.averageAmount),
            monthlyAverage = intl.formatMessage(messages.monthlyAverage);

        let c = currencySymbol || currency || unit.currencySymbol || unit.currency;

        console.warn(this.props);

        return (
            <div className="relative">
                    { data ? (
                        <div className="center">
                            <LabeledValue label={ totalLabel } size="big">
                                { formatMoney(data.total, c, i18n) }
                            </LabeledValue>
                            <LabeledValue label={ averageAmount } size="big">
                                { formatMoney(data.averageAmount, c, i18n) }
                            </LabeledValue>
                            <LabeledValue label={ monthlyAverage } size="big">
                                { formatMoney(data.monthlyAverage, c, i18n) }
                            </LabeledValue>
                        </div> 
                    ): null }
                {<ActivityIndicator show={ status === "pending" } type="overlay" size="big" />}
            </div>
        );  
    }
}

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


let chartOptions = {
    cutoutPercentage: 65,
    animate: false,
    maintainAspectRatio: false,
    legend: {
        animate: false,
        display: false 
    },
    animate: false,
    animation: {
        animateScale: false,
        animateRotate: false,
    },    
};

function renderTooltip(i18n, labels, currency, empty) {
    if (empty) {
        return () => {
            return formatMoney(0, currency, i18n);
        };
    }
    return (tooltipItem, data) => {
        let dataset = data.datasets[tooltipItem.datasetIndex];
        let total = dataset.data.reduce(function(previousValue, currentValue, currentIndex, array) {
            return previousValue + currentValue;
        });
        let currentValue = dataset.data[tooltipItem.index];
        return formatMoney(currentValue, currency, i18n) + " (" + formatPercent(currentValue / total * 100, i18n) + ")";
    }
}

class ExpenseSuppliersChart extends Component {

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

        //TODO refactor
        let sums = [];
        let labels = [];
        let colors = [];
        let percents = [];
        let total = 0;
        let legend = null;

        let { currencySymbol, currency } = data || {};
        currency = currencySymbol || currency || unit.currencySymbol || unit.currency;

        let empty = !(data && Array.isArray(data.data) && data.data.length); 
        if (!empty) {
            colors = palette(global._chartColors, data.data.length);
        
            for (let i = 0; i < data.data.length; i++) {
                let d = data.data[i];
                sums.push(d.total);
                labels.push(d.name || d.idNumber);
                total += d.total;
            }

            if (total) {
                sums.map(s => percents.push(s / total * 100));
            }

            legend = <DoughnutChartLegend labels={ labels } colors={ colors } values={ sums } percents={ percents } currency={ currency } i18n={ i18n } />

        } else {
            colors = ["#BEBEBE"];
            sums.push(1);
            labels.push("");

            legend = <DoughnutChartLegend labels={ [
                intl.formatMessage(messages.suppliersChartEmpty)] } colors={ colors } values={ [0] } percents={ [0] } currency={ currency } i18n={ i18n } />
        }

        let chartData = {
            labels: labels,
            datasets: [{
                data: sums,
                backgroundColor: colors
            }]
        };


        return (
            <div className="p10">
                <div className="status-chart relative">
                    <div>
                        <div className="status-chart-div">
                            <Doughnut data={ chartData } options={ { ...chartOptions, tooltips: { callbacks: { label: renderTooltip(i18n, labels, currency, empty || !total) }} } } redraw={ true }/>
                        </div>
                    </div>
                    <div>
                        { legend }
                    </div>
                    <ActivityIndicator show={ status === "pending" } type="overlay" size="big" />
                </div>
            </div>
        );  
    }
}

ExpenseSuppliersChart = connect(settingsSelector((state, props) => state.getIn(["expenseList", "suppliers"]).toJS()), () => ({}) )(ExpenseSuppliersChart);
ExpenseSuppliersChart = injectIntl(ExpenseSuppliersChart);


//TODO



class Expenses extends Component {


    constructor(props) {
        super(props);
        this.changePeriod = this.changePeriod.bind(this);
    }


	componentWillMount() {
        this.changePeriod(this.props.periodParams, this.props.list.paging, this.props.list.sorting);
    }


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

        this.props.fetchList(unitId, { from, to, dateType });
        this.props.fetchSummary(unitId, { from, to, dateType });
        this.props.fetchSuppliers(unitId, { from, to, dateType });
        this.props.fetchTimeline(unitId, { from, to, dateType });
    }


	render() {
		let { intl, list, timeline } = this.props;
		let content = null;
		let pending = list.status == "pending";

		return (
			<div className="pv10">
                <Toolbar>
                    <ToolbarSection>
                        <ListTitle 
                            title={ intl.formatMessage(messages.title) }
                            titleIcon={ icons.expenses }
                            />
                    </ToolbarSection>
                    <ToolbarButtons>
                        <ToolbarButton 
                            label={ intl.formatMessage(messages.addExpense) }
                            onClick={ () => this.context.router.push("/expenses/new") } 
                            >
                            <span className="icon">{ icons.add }</span>
                        </ToolbarButton>
                    </ToolbarButtons>
                    <ToolbarRow>
                        <PeriodTitle
                            size="normal"
                            changePeriod={ this.changePeriod }
                            />
                    </ToolbarRow>
                </Toolbar>

                <div className="dashboard-row">
                    <div className="col-md-6 p10">
                        <FetchedContent 
                            status={ list.status } 
                            error={ list.error } 
                            fresh={ list.fresh } 
                            empty={ !list.data || !list.data.length } 
                            size="big"
                            buttons={ (                        
                                <ToolbarButton 
                                    label={ intl.formatMessage(messages.addExpense) }
                                    onClick={ () => this.context.router.push("/expenses/new") } 
                                    >
                                    <span className="icon">{ icons.add }</span>
                                </ToolbarButton>
                            ) }>

                            <ExpenseList 
                                items={ list.data } 
                                onDetailClick={ (id) => this.context.router.push(`/expenses/${id}`)} 
                                disabled={ pending }
                                />
                            { list.data ? 
                                <PageSwitcher
                                    paging={ list.paging } 
                                    onPageChanged={ (paging) => this.props.fetchList(this.props.unitId, list.filter, paging, list.sorting) } 
                                    status={ list.status } 
                                    disabled={ pending }
                                    /> : null 
                            }

                        </FetchedContent>
                    </div>
                    <div className="col-md-6 p10">
                        <div className="flex-auto flex-wrap-reverse">
                            <div className="hover-highlight-light mv20 p10">
                                <h2 className="mb20">{ intl.formatMessage(messages.suppliersChart) }</h2>
                                <ExpenseSuppliersChart />
                            </div>
                            <div className="hover-highlight-light mv20 p10">
                                <ExpensesSummary />
                            </div>
                        </div>
                        <div className="hover-highlight-light mv20 p10 relative">
                            <h2 className="mb20">{ intl.formatMessage(messages.timelineChart) }</h2>
                            { timeline ? <ExpenseTimelineChart { ...timeline.data } status={ timeline.status } /> : null }
                            <ActivityIndicator show={ timeline && timeline.status === "pending" } type="overlay" size="big" />
                        </div>
                        {/*<div>
                            <SectionHeader 
                                title={ intl.formatMessage({ id: "customers.page.overview.title" }) }
                                />
                            { this.renderReport(intl, report) }
                        </div>*/}
                    </div>
                </div>

			</div>
		);
	}

}

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



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



function mapDispatchToProps(dispatch, props) {
	return {
		dispatch,
		fetchList: (unitId, filter, paging, sorting) => dispatch(fetchList(filter, paging, sorting, { unitId })),
        expenseReport: (unitId, params) => dispatch(expenseReportAction(unitId, params)),
        fetchSummary: (unitId, filter) => dispatch(fetchSummary(unitId, filter)),
        fetchSuppliers: (unitId, filter) => dispatch(fetchSuppliers(unitId, filter)),
        fetchTimeline: (unitId, filter) => dispatch(fetchTimeline(unitId, filter)),
  	};
}


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