var React = require('react');
var ReactDOM = require('react-dom');

var _ = require('lodash');
var Maths = require('../utils/Maths');
var Legend = require('./Legend.jsx');

var Column_series = require('./Column_series.jsx');
var ClassMixin = require('../mixins/ClassMixin');

var _MAX_TICKS = 10;

var Column = React.createClass({
    displayName: 'Column',
    mixins: [ClassMixin],
    propTypes: {
        data: React.PropTypes.oneOfType([
            React.PropTypes.array,
            React.PropTypes.object
        ]).isRequired,
        colors: React.PropTypes.arrayOf(React.PropTypes.string),
        displayAxis: React.PropTypes.bool,
        xAxisLabel: React.PropTypes.func,
        yAxisLabel: React.PropTypes.oneOfType([
            React.PropTypes.string,
            React.PropTypes.func
        ]),
        yValueLabel: React.PropTypes.func,
        columnStyle: React.PropTypes.func,
        yMax: React.PropTypes.number,
        yAxisMax: React.PropTypes.number
    },
    getDefaultProps: function() {
        return {
            data: [],
            colors: ['#FDC855', '#FD9457'],
            tickInterval: 1,
            series: null,
            xAxisLabel: null,
            displayAxis: true,
            yValueLabel: null,

            yMax: null,

            columnStyle: null
        };
    },
    getInitialState: function () {
        return {
            tooltipValue: {},
            mouseCoordinates: [0, 0],
            tooTight: false
        };
    },
    componentDidMount: function () {
        this.setState({containerSize: ReactDOM.findDOMNode(this).offsetHeight});
    },
    // onMouseMove: function (e) {
    //     var dom = this.refs.wrapper.getDOMNode();
    //     var main = this.refs.main.getDOMNode();
    //     console.dir(main);
    //     var ct = e.currentTarget;
    //     var top = e.currentTarget.offsetTop + e.currentTarget.offsetHeight;
    //     // var left = e.currentTarget.offsetWidth;

    //     var left = 0;

    //     // console.log(ct.offsetWidth, ct.offsetLeft, e.clientX, dom.offsetLeft);

    //     this.setState({
    //         mouseCoordinates: [e.clientX - left, e.clientY - top]
    //     });
    // },
    onColumnWrapperOver: function () {
        // this.setState({
        //     tooltipValue: value.series,
        // });
    },
    onColumnOver: function (value) {
        this.setState({
            currentValue: value,
            hover: true
        });
    },
    onColumnOut: function (e) {
        if(e.currentTarget === e.target) {
            this.setState({hover: false});
        }
    },
    getComputedValues: function(data, tickInterval) {
        data = data || this.props.data;

        // Convert immutable to JS
        if (data.size && data.toJS) {
            data = data.toJS();
        }

        tickInterval = tickInterval || this.props.tickInterval;

        var _values = _.chain(data)
            .map('series')
            .flatten()
            .remove(null)
            .value();

        var extent = Maths.extent(_values);

        var max = extent[1] || 0;

        if(this.props.yAxisMax) {
            max = this.props.yAxisMax;
        }

        var roundToNearest = tickInterval;
        var roundMax = Math.ceil(max / roundToNearest) * roundToNearest;
        var numberOfTicks = roundMax / tickInterval;

        if (numberOfTicks > _MAX_TICKS) {
            var nextTickInterval = tickInterval * 2;

            // To avoid going over the yMax
            if (this.props.yMax && roundMax > this.props.yMax) {
                if (this.props.tickInterval === 1 || this.props.tickInterval % 2 === 0) {
                    nextTickInterval = 5;
                }
                else {
                    nextTickInterval = 1;
                }
            }

            // Keep increasing the tickInterval until we get less than the _MAX_TICKS ticks
            return this.getComputedValues(data, nextTickInterval);
        }

        return {
            min: extent[0] || 0,
            max: roundMax,
            numberOfTicks: numberOfTicks
        };
    },
    render: function () {
        var classes = this.createClassName('Column');
        var data = this.props.data;

        // Convert immutable to JS
        if (data.size && data.toJS) {
            data = data.toJS();
        }

        var computedValues = this.getComputedValues(data, this.props.tickInterval);

        return (
            <div ref="main"className={classes.className}>
                {this.renderLegend()}
                {this.renderYAxis(computedValues)}
                {this.renderColumns(data, computedValues)}
                {this.renderValueBar(computedValues)}
                {this.renderTooltip(this.state.tooltipValue)}
            </div>
        );
    },
    renderLegend: function () {
        if (!this.props.legend) {
            return null;
        }

        return <Legend legend={this.props.legend} colors={this.props.colors}></Legend>;
    },
    renderLegendItem: function (series, key) {
        return <li className="Column_seriesItem" key={key} data-label={series} style={{borderColor: this.props.colors[key]}}></li>;
    },
    renderYAxis: function (computedValues) {
        if (this.props.displayAxis) {
            var range = [];

            if (computedValues.numberOfTicks > 0) {
                range = Maths.tickRange(computedValues.numberOfTicks, 0, computedValues.max);
            }

            return (
                <div className="Column_yaxis">
                    <div className="Graph_ytitle">{this.props.yAxisLabel}</div>
                    {_.map(range, function(key, i) {
                        var lbl = key;

                        if (this.props.yValueLabel) {
                            lbl = this.props.yValueLabel(key, i);
                        }

                        var style = {
                            height: (100 / (range.length - 1) + '%')
                        };

                        return <div key={i} className="Column_ylabel" style={style}>{lbl !== undefined ? lbl : key}</div>;
                    }.bind(this))}
                </div>
            );
        }
    },
    renderColumns: function (data, computedValues) {
        var columns = _.map(data, (column, columnIndex) => {
            var stackSize = 0;
            var totalStackSize = 0;

            column.series.forEach(function(val) {
                totalStackSize += val;
            });

            var series = _.map(column.series, (vv, ii) => {
                stackSize += vv;
                return this.renderSeries(vv, ii, column, computedValues, stackSize, totalStackSize);
            }).reverse();

            // console.log(series);



            // var seriesOrder = (this.props.type === 'accumulative') ? series.reverse() : series;

            return (
                <div key={columnIndex} className="Column_col" style={{width: 100 / data.length + '%'}}>
                    <div className="Column_seriesWrapper" onMouseOver={this.onColumnWrapperOver.bind(this, column)}>
                        {series}
                    </div>
                    <div className="Graph_xlabel Column_xlabel">{this.renderXLabel(column, columnIndex)}</div>
                </div>
            );
        });
        return (
            <div className="Column_wrapper">{columns}</div>
        );
    },
    renderXLabel: function (column, columnIndex) {
        var xlabel = column.xlabel;
        if (this.props.displayAxis) {
            if (this.props.xAxisLabel) {
                xlabel = this.props.xAxisLabel(column.xlabel, columnIndex);
            }

            return xlabel !== undefined ? xlabel : column.xlabel;
        }
        // return "\u00a0"; // Non breaking space;
    },
    renderSeries: function(value, seriesIndex, column_data, computedValues, stackSize, totalStackSize) {
        var yPos = stackSize - value;
        var yPercent = (yPos / totalStackSize) * 100;

        var newValue = value;

        if(this.props.type === 'stacked') {
            newValue = value + yPos;
        }

        return <Column_series
            value={newValue}
            yPos={yPercent}
            key={seriesIndex}
            seriesIndex={seriesIndex}
            containerSize={this.state.containerSize}
            column_data={column_data}
            columnStyle={this.props.columnStyle}
            colors={this.props.colors}
            computedValues={computedValues}
        />;
    },
    renderValueBar: function () {
        var style = {
            top: this.state.currentValue + '%',
            opacity: 0
        };

        if(this.state.hover) {
            style.opacity = 1;
        }

        return <div className="Column_valueBar" style={style}></div>;
    },
    renderTooltip: function (data) {
        var style = {
                top: this.state.mouseCoordinates[1],
                left: this.state.mouseCoordinates[0],
                opacity: 0
            },
            series;

        if(this.state.hover) {
            style.opacity = 1;
        }


        if(data) {
            series = _.map(data, function (value, key) {
                return this.renderSeriesItem(value, key);
            }.bind(this));
        }

        return <div className="Column_tooltip" style={style}>
            <ul>{series}</ul>
        </div>;
    }
});

module.exports = Column;