// Global vars
var MOBILE_THRESHOLD = 600;
var pymChild = null;
var isMobile = false;

/*
 * Initialize the graphic.
 */
var onWindowLoaded = function() {
    if (Modernizr.svg) {
        formatData();

        pymChild = new pym.Child({
            renderCallback: render
        });
    } else {
        pymChild = new pym.Child({});
    }

    pymChild.onMessage('on-screen', function(bucket) {
        ANALYTICS.trackEvent('on-screen', bucket);
    });
    pymChild.onMessage('scroll-depth', function(data) {
        data = JSON.parse(data);
        ANALYTICS.trackEvent('scroll-depth', data.percent, data.seconds);
    });
}

/*
 * Format graphic data for processing by D3.
 */
var formatData = function() {
    DATA.forEach(function(d) {
        for (key in d) {
            if (key == 'Group') {
                continue;
            }
            d[key] = Number(d[key]) * 100;
        }
    });
}

/*
 * Render the graphic(s). Called by pym with the container width.
 */
var render = function(containerWidth) {
    if (!containerWidth) {
        containerWidth = DEFAULT_WIDTH;
    }

    var graphicWidth = null;
    var gutterWidth = 22;
    var labelWidth = 105;
    var labelGap = 10;
    var numCols = null;

    if (containerWidth <= MOBILE_THRESHOLD) {
        labelWidth = 75;
        isMobile = true;
        numCols = 2;
    } else {
        isMobile = false;
        numCols = 3;
    }
    graphicWidth = Math.floor((containerWidth - (gutterWidth * (numCols - 1)) - labelWidth - labelGap) / numCols);

    // Clear existing graphic (for redraw)
    var containerElement = d3.select('#bar-chart');
    containerElement.html('');

    var charts = d3.keys(DATA[0]).filter(function(d) {
        return d != 'Group';
    });

    var colorScale = d3.scale.ordinal()
        .domain(charts)
        .range([
          COLORS['teal3'],
          '#999',
          COLORS['orange3'],
          '#999'
        ]);

    charts.forEach(function(d,i) {
        var thisGraphicWidth = graphicWidth;
        var showLabels = false;
        if (i % numCols == 0) {
            thisGraphicWidth += labelWidth + labelGap;
            showLabels = true;
        }

        // containing div
        var chartElement = containerElement.append('div')
            .attr('class', 'chart c-' + classify(d));
        chartElement.attr('style', function() {
            var s = '';
            s += 'width: ' + thisGraphicWidth + 'px; ';
            s += 'float: left; ';
            if (!showLabels) {
                s += 'margin-left: ' + gutterWidth + 'px; ';
            }
            return s;
        });

        var header = chartElement.append('h3')
            .text(d);
        if (showLabels) {
            header.attr('style', 'padding-left:' + (labelWidth + labelGap) + 'px;');
        }

        // Render the chart!
        renderBarChart({
            container: '.chart.c-' + classify(d),
            width: thisGraphicWidth,
            data: DATA,
            dataColumn: d,
            domain: [ 0, 100 ],
            showLabels: showLabels,
            labelWidth: labelWidth,
            labelGap: labelGap,
            colorScale: colorScale
        });
    })

    resizeSubheds('#bar-chart');

    // Update iframe
    if (pymChild) {
        pymChild.sendHeight();
    }
}


/*
 * Render a bar chart.
 */
var renderBarChart = function(config) {
    /*
     * Setup
     */
    var labelColumn = 'Group';
    var valueColumn = config['dataColumn'];

    var barHeight = 30;
    var barGap = 5;
    var labelWidth = config['labelWidth'];
    var labelMargin = config['labelGap'];
    var valueGap = 6;

    var margins = {
        top: 0,
        right: 0,
        bottom: 0,
        left: (labelWidth + labelMargin)
    };

    if (!config['showLabels']) {
        margins['left'] = 0;
    }

    var ticksX = 4;
    var roundTicksFactor = 100;
    var colorScale = config['colorScale'];

    // Calculate actual chart dimensions
    var chartWidth = config['width'] - margins['left'] - margins['right'];
    var chartHeight = ((barHeight + barGap) * config['data'].length) - barGap;

    // Clear existing graphic (for redraw)
    var containerElement = d3.select(config['container']);
    // containerElement.html('');

    /*
     * Create the root SVG element.
     */
    var chartWrapper = containerElement.append('div')
        .attr('class', 'graphic-wrapper');

    var chartElement = chartWrapper.append('svg')
        .attr('width', chartWidth + margins['left'] + margins['right'])
        .attr('height', chartHeight + margins['top'] + margins['bottom'])
        .append('g')
        .attr('transform', 'translate(' + margins['left'] + ',' + margins['top'] + ')');

    /*
     * Create D3 scale objects.
     */
    var min = config['domain'][0];

    if (min > 0) {
        min = 0;
    }

    var max = config['domain'][1];

    var xScale = d3.scale.linear()
        .domain([min, max])
        .range([0, chartWidth]);

    /*
     * Create D3 axes.
     */
    var xAxis = d3.svg.axis()
        .scale(xScale)
        .orient('bottom')
        .ticks(ticksX)
        .tickFormat(function(d) {
            return d.toFixed(0) + '%';
        });

    chartElement.append('g')
        .attr('class', 'bg')
        .selectAll('rect')
        .data(config['data'])
        .enter().append('rect')
            .attr('class', 'bg')
            .attr('x', xScale(xScale.domain()[0]))
            .attr('width', chartWidth)
            .attr('y', function(d,i) {
                return i * (barHeight + barGap);
            })
            .attr('height', barHeight);

    /*
     * Render bars to chart.
     */
    chartElement.append('g')
        .attr('class', 'bars')
        .selectAll('rect')
        .data(config['data'])
        .enter()
        .append('rect')
            .attr('x', function(d) {
                if (d[valueColumn] >= 0) {
                    return xScale(0);
                }
                return xScale(d[valueColumn]);
            })
            .attr('width', function(d) {
                return Math.abs(xScale(0) - xScale(d[valueColumn]));
            })
            .attr('y', function(d, i) {
                return i * (barHeight + barGap);
            })
            .attr('height', barHeight)
            .attr('fill', function(d) {
              return colorScale(valueColumn);
            })
            .attr('class', function(d, i) {
                return 'bar-' + i + ' ' + classify(d[labelColumn]);
            });

    /*
     * Render bar labels.
     */
    if (config['showLabels']) {
        chartWrapper.append('ul')
            .attr('class', 'labels')
            .attr('style', formatStyle({
                'width': labelWidth + 'px',
                'top': margins['top'] + 'px',
                'left': '0'
            }))
            .selectAll('li')
            .data(config['data'])
            .enter()
            .append('li')
                .attr('style', function(d, i) {
                    return formatStyle({
                        'width': labelWidth + 'px',
                        'height': barHeight + 'px',
                        'left': '0px',
                        'top': (i * (barHeight + barGap)) + 'px;'
                    });
                })
                .attr('class', function(d) {
                    return classify(d[labelColumn]);
                })
                .append('span')
                    .text(function(d) {
                        return d[labelColumn];
                    });
    }

    /*
     * Render bar values.
     */
    chartElement.append('g')
        .attr('class', 'value')
        .selectAll('text')
        .data(config['data'])
        .enter()
        .append('text')
            .text(function(d) {
                return d[valueColumn].toFixed(0) + '%';
            })
            .attr('class', function(d) {
                return classify(d[labelColumn]);
            })
            .attr('x', function(d) {
                return xScale(d[valueColumn]);
            })
            .attr('y', function(d, i) {
                return i * (barHeight + barGap);
            })
            .attr('dx', function(d) {
                var xStart = xScale(d[valueColumn]);
                var textWidth = this.getComputedTextLength()

                // Negative case
                if (d[valueColumn] < 0) {
                    var outsideOffset = -(valueGap + textWidth);

                    if (xStart + outsideOffset < 0) {
                        d3.select(this).classed('in', true)
                        return valueGap;
                    } else {
                        d3.select(this).classed('out', true)
                        return outsideOffset;
                    }
                // Positive case
                } else {
                    if (xStart + valueGap + textWidth > chartWidth) {
                        d3.select(this).classed('in', true)
                        return -(valueGap + textWidth);
                    } else {
                        d3.select(this).classed('out', true)
                        return valueGap;
                    }
                }
            })
            .attr('dy', (barHeight / 2) + 3);
}

// resize subheds
var resizeSubheds = function(containerElement) {
    var labelHeds = d3.select(containerElement).selectAll('h3');
    var labelMaxHeight = 0;

    labelHeds[0].forEach(function(d,i) {
        var thisHeight = d.getBoundingClientRect().height;
        if (thisHeight > labelMaxHeight) {
            labelMaxHeight = thisHeight;
        }
    });

    labelHeds.style('height', labelMaxHeight + 'px');
}


/*
 * Initially load the graphic
 * (NB: Use window.load to ensure all images have loaded)
 */
window.onload = onWindowLoaded;
