var BarChart = React.createClass({
    mixins: [ReactRouter.Navigation, ReactRouter.State, SVGChartMixin, ChartDataMixin],
    sorts: ['commits', 'delta'],
    numElements: 15,
    barHeight: 30,
    barMargin: 5,
    getInitialState: function() {
        return {
            item: this.props.items[0],
            sort: 'commits',
            rawData: [],
            points: [],
            min: 0,
            max: 1
        };
    },
    componentDidMount: function() {
        this.calculateViewBoxWidth();
        window.addEventListener('resize', this.calculateViewBoxWidth);
        this.componentWillReceiveProps(this.props);
    },
    componentWillReceiveProps: function(newProps) {
        this.setState({
            item: newProps.items[0],
            sort: 'commits',
            state: 'newProps'
        }, this.fetchData);
    },
    shouldComponentUpdate: function(newProps, newState) {
        if (!newState.canvasWidth) {
            return false;
        }
        if (newState.state !== 'newPoints')  {
            return false;
        }
        return true;
    },
    handleFilter: function(thing, i) {
        if (thing === 'item' && this.props.items[i] !== this.state.item) {
            this.setState({
                item: this.props.items[i],
                state: 'newProps'
            }, this.fetchData);
        } else if (thing === 'sort' && this.sorts[i] !== this.state.sort) {
            this.setState({
                sort: this.sorts[i],
                state: 'newProps'
            }, this.handleNewData);
        }
    },
    handleClick: function(point) {
        var params = {org: this.getParams().org};
        params[this.state.item] = point.item;
        this.transitionTo(this.state.item, params);
    },
    handleNewData: function() {
        var min = 0, max = 1;
        var points = _.chain(this.state.rawData)
            .sort(function(a, b) {
                return Math.abs(b[this.state.sort]) - Math.abs(a[this.state.sort]);
            }.bind(this))
            .take(this.numElements)
            .value();
        for (var i = points.length; i < this.numElements; i++) {
            var point = {};
            point[this.state.sort] = 0;
            points.push(point);
        }
        this.setState({
            points: points,
            min: _.min(points, this.state.sort)[this.state.sort],
            max: _.max(points, this.state.sort)[this.state.sort],
            state: 'newPoints'
        });
    },
    height: function() {
        if (this.state.points.length === 0) {
            return 0;
        } else {
            return this.y(this.state.points.length) - this.barMargin;
        }
    },
    y: function(i) {
        return i*(this.barHeight + this.barMargin);
    },
    render: function() {
        var words = {
                items: {
                    repo: 'repositories',
                    team: 'teams',
                    user: 'contributors'
                },
                item: {
                    repo: 'repository',
                    team: 'team',
                    user: 'author'
                },
                actions: {
                    repo: 'which were the most attended by',
                    team: 'which were the most active working on',
                    user: 'which were the most active working on'
                }
            },
            who = this.getParams().repo || this.getParams().team || this.getParams().user || this.getParams().org,
            params = Object.keys(this.getParams());
        params.splice(params.indexOf('org'), 1);
        return (
            
                
                    This bar chart represents {words.items[this.state.item]} {words.actions[this.state.item]} {who} {words.item[params[0]]} from W11, Mar 9 to W18, Apr 27
                
                
                    
                    
                
                
             
        );
    },
    renderBar: function(point, i) {
        var maxWidth = this.state.canvasWidth,
            val = point[this.state.sort],
            min = this.state.min,
            max = this.state.max,
            max2 = (min < 0 ? max - min : max),
            width = Math.floor(Math.abs(val)/max2*maxWidth),
            height = this.barHeight,
            offset = (min < 0 ? -min : 0)/max2*maxWidth,
            x = (min >= 0 ? 0 : offset - (val >= 0 ? 0 : width)),
            y = this.y(i);
        return (
            
        );
    }
});
var Bar = React.createClass({
    mixins: [ReactRouter.Navigation, ChartAnimationMixin],
    height: 30,
    labelPaddingH: 5,     // Label horizontal padding
    labelPaddingV: 2,     // Label vertical padding
    labelMarginV: 5,      // Same as padding
    labelHeight: 16,      // Text size
    labelOuterHeight: 20, // labelHeight + 2*labelPaddingV,
    getInitialState: function() {
        return {
            labelX: 0,
            lastLabelX: 2*this.labelPaddingH
        };
    },
    componentDidMount: function() {
        this.calculateLabelPosition();
    },
    componentWillReceiveProps: function(newProps) {
        if (_.isEqual(this.props, newProps)) {
            return;
        }
        this.setState({
            lastBarX: (this.props.x !== undefined ? this.props.x : newProps.x),
            lastBarWidth: (this.props.width !== undefined ? this.props.width : newProps.width),
            lastLabelX: this.state.labelX
        }, this.calculateLabelPosition);
    },
    calculateLabelPosition: function() {
        var val = this.props.value,
            offset = this.props.offset,
            label = this.props.item + ': ' + numberFormat(val),
            labelWidth = textWidth(label),
            labelOuterWidth = labelWidth + 2*this.labelPaddingH,
            labelOffsetWidth = labelOuterWidth + 2*this.labelPaddingH,
            labelX;
        if (offset === 0) {
            labelX = 2*this.labelPaddingH;
        } else {
            if (val < 0) {
                if (offset >= labelOffsetWidth) {
                    labelX = offset - labelOffsetWidth + 2*this.labelPaddingH;
                } else {
                    labelX = offset + 2*this.labelPaddingH;
                }
            } else {
                if (offset + labelOffsetWidth <= this.props.max) {
                    labelX = offset + 2*this.labelPaddingH;
                } else {
                    labelX = offset - labelOffsetWidth + 2*this.labelPaddingH;
                }
            }
        }
        this.setState({
            labelX: labelX
        }, this.animateAll);
    },
    animateAll: function() {
        var bar = this.refs.bar,
            underlay = this.refs.label.refs.underlay,
            text = this.refs.label.refs.text,
            padH = this.labelPaddingH;
        this.clearAnimations(bar);
        this.clearAnimations(underlay);
        this.clearAnimations(text);
        this.animate(bar, 'width', this.state.lastBarWidth, this.props.width);
        this.animate(bar, 'x', this.state.lastBarX, this.props.x);
        this.animate(underlay, 'x', this.state.lastLabelX - padH, this.state.labelX - padH);
        this.animate(text, 'x', this.state.lastLabelX, this.state.labelX);
    },
    render: function() {
        var label = this.props.item ? (this.props.item + ': ' + numberFormat(this.props.value)) : '',
            labelWidth = textWidth(label),
            labelOuterWidth = (labelWidth == 0 ? 0 : labelWidth + 2*this.labelPaddingH),
            barX = (this.state.lastBarX && this.state.lastBarX !== this.props.x
                ? this.state.lastBarX
                : this.props.x),
            barWidth = (this.state.lastBarWidth && this.state.lastBarWidth !== this.props.width
                ? this.state.lastBarWidth
                : this.props.width);
        return (
            
                
                
            
        );
    }
});
var BarLabel = React.createClass({
    render: function() {
        var text = (this.props.item ? this.props.item +': '+ numberFormat(this.props.value) : '');
        return (
            
                
                
                    {text}
                
            
        );
    }
})