/*!
 * chartjs-plugin-trendline.js
 * Version: 0.1.3
 *
 * Copyright 2017 Marcus Alsterfjord
 * Released under the MIT license
 * https://github.com/Makanz/chartjs-plugin-trendline/blob/master/README.md
 *
 * Mod by: vesal: accept also xy-data so works with scatter
 */
var pluginTrendlineLinear = {
  afterDatasetsDraw: function (chartInstance) {
    var yScale;
    var xScale;
    for (var axis in chartInstance.scales) {
      if (axis[0] == "x") xScale = chartInstance.scales[axis];
      else yScale = chartInstance.scales[axis];
      if (xScale && yScale) break;
    }
    var ctx = chartInstance.chart.ctx;

    chartInstance.data.datasets.forEach(function (dataset, index) {
      if (dataset.trendlineLinear && chartInstance.isDatasetVisible(index)) {
        var datasetMeta = chartInstance.getDatasetMeta(index);
        addFitter(datasetMeta, ctx, dataset, xScale, yScale);
      }
    });

    ctx.setLineDash([]);
  },
};

function addFitter(datasetMeta, ctx, dataset, xScale, yScale) {
  if (
    datasetMeta.data == [] ||
    datasetMeta.data == null ||
    datasetMeta.data.length == 0
  )
    return;
  var style = dataset.trendlineLinear.style || dataset.borderColor;
  var lineWidth = dataset.trendlineLinear.width || dataset.borderWidth;
  var lineStyle = dataset.trendlineLinear.lineStyle || "solid";

  style = style !== undefined ? style : "rgba(169,169,169, .6)";
  lineWidth = lineWidth !== undefined ? lineWidth : 3;

  var fitter = new LineFitter();
  var lastIndex = dataset.data.length - 1;
  var startPos = datasetMeta.data[0]._model.x;
  var endPos = datasetMeta.data[lastIndex]._model.x;

  var xy = false;
  if (dataset.data && typeof dataset.data[0] === "object") xy = true;

  dataset.data.forEach(function (data, index) {
    if (data == null) return;
    if (xy) fitter.add(data.x, data.y);
    else fitter.add(index, data);
  });

  var x1 = xScale.getPixelForValue(fitter.minx);
  var x2 = xScale.getPixelForValue(fitter.maxx);
  var y1 = yScale.getPixelForValue(fitter.f(fitter.minx));
  var y2 = yScale.getPixelForValue(fitter.f(fitter.maxx));
  if (!xy) {
    x1 = startPos;
    x2 = endPos;
  }

  var drawBottom = datasetMeta.controller.chart.chartArea.bottom;
  var chartWidth = datasetMeta.controller.chart.width;

  if (y1 > drawBottom) {
    // Left side is below zero
    var diff = y1 - drawBottom;
    var lineHeight = y1 - y2;
    var overlapPercentage = diff / lineHeight;
    var addition = chartWidth * overlapPercentage;

    y1 = drawBottom;
    x1 = x1 + addition;
  } else if (y2 > drawBottom) {
    // right side is below zero
    var diff = y2 - drawBottom;
    var lineHeight = y2 - y1;
    var overlapPercentage = diff / lineHeight;
    var subtraction = chartWidth - chartWidth * overlapPercentage;

    y2 = drawBottom;
    x2 = chartWidth - (x2 - subtraction);
  }

  ctx.lineWidth = lineWidth;
  if (lineStyle === "dotted") {
    ctx.setLineDash([6, 6]);
  }
  ctx.beginPath();
  ctx.moveTo(x1, y1);
  ctx.lineTo(x2, y2);
  ctx.strokeStyle = style;
  ctx.stroke();
}

Chart.plugins.register(pluginTrendlineLinear);

function LineFitter() {
  this.count = 0;
  this.sumX = 0;
  this.sumX2 = 0;
  this.sumXY = 0;
  this.sumY = 0;
  this.minx = 1e100;
  this.maxx = -1e100;
}

LineFitter.prototype = {
  add: function (x, y) {
    this.count++;
    this.sumX += x;
    this.sumX2 += x * x;
    this.sumXY += x * y;
    this.sumY += y;
    if (x < this.minx) this.minx = x;
    if (x > this.maxx) this.maxx = x;
  },
  f: function (x) {
    var det = this.count * this.sumX2 - this.sumX * this.sumX;
    var offset = (this.sumX2 * this.sumY - this.sumX * this.sumXY) / det;
    var scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
    return offset + x * scale;
  },
};
