"use strict";

module.exports = function (Chart) {

    var helpers = Chart.helpers;

    Chart.defaults.bubble = {
        hover: {
            mode: "single"
        },

        scales: {
            xAxes: [{
                type: "linear", // bubble should probably use a linear scale by default
                position: "bottom",
                id: "x-axis-0" // need an ID so datasets can reference the scale
            }],
            yAxes: [{
                type: "linear",
                position: "left",
                id: "y-axis-0"
            }]
        },

        tooltips: {
            callbacks: {
                title: function (tooltipItems, data) {
                    // Title doesn't make sense for scatter since we format the data as a point
                    return '';
                },
                label: function (tooltipItem, data) {
                    var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
                    var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
                    return datasetLabel + ': (' + dataPoint.x + ', ' + dataPoint.y + ', ' + dataPoint.r + ')';
                }
            }
        }
    };

    Chart.controllers.bubble = Chart.DatasetController.extend({

        dataElementType: Chart.elements.Point,

        update: function update(reset) {
            var meta = this.getMeta();
            var points = meta.data;

            // Update Points
            helpers.each(points, function (point, index) {
                this.updateElement(point, index, reset);
            }, this);
        },

        updateElement: function (point, index, reset) {
            var meta = this.getMeta();
            var xScale = this.getScaleForId(meta.xAxisID);
            var yScale = this.getScaleForId(meta.yAxisID);

            var custom = point.custom || {};
            var dataset = this.getDataset();
            var data = dataset.data[index];
            var pointElementOptions = this.chart.options.elements.point;

            helpers.extend(point, {
                // Utility
                _xScale: xScale,
                _yScale: yScale,
                _datasetIndex: this.index,
                _index: index,

                // Desired view properties
                _model: {
                    x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(data, index, this.index, this.chart.isCombo),
                    y: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, this.index),
                    // Appearance
                    radius: reset ? 0 : custom.radius ? custom.radius : this.getRadius(data),
                    backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, pointElementOptions.backgroundColor),
                    borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, pointElementOptions.borderColor),
                    borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, pointElementOptions.borderWidth),

                    // Tooltip
                    hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)
                }
            });

            var model = point._model;
            model.skip = custom.skip ? custom.skip : (isNaN(model.x) || isNaN(model.y));

            point.pivot();
        },

        getRadius: function (value) {
            return value.r || this.chart.options.elements.point.radius;
        },

        setHoverStyle: function (point) {
            // Point
            var dataset = this.chart.data.datasets[point._datasetIndex];
            var index = point._index;
            var custom = point.custom || {};
            var model = point._model;

            model.radius = custom.hoverRadius ? custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, this.chart.options.elements.point.hoverRadius)) + this.getRadius(this.getDataset().data[point._index]);
            model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
            model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));
            model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
        },

        removeHoverStyle: function (point) {
            var dataset = this.chart.data.datasets[point._datasetIndex];
            var index = point._index;
            var custom = point.custom || {};
            var model = point._model;
            var pointElementOptions = this.chart.options.elements.point;

            model.radius = custom.radius ? custom.radius : this.getRadius(dataset.data[point._index]);
            model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, pointElementOptions.backgroundColor);
            model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, pointElementOptions.borderColor);
            model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, pointElementOptions.borderWidth);
        }
    });
};
