var util = require('../../util');
var DOMutil = require('../../DOMutil');
var Bars = require('./graph2d_types/bar');
var Lines = require('./graph2d_types/line');
var Points = require('./graph2d_types/points');

/**
 * /**
 * @param {object} group            | the object of the group from the dataset
 * @param {string} groupId          | ID of the group
 * @param {object} options          | the default options
 * @param {array} groupsUsingDefaultStyles  | this array has one entree.
 *                                            It is passed as an array so it is passed by reference.
 *                                            It enumerates through the default styles
 * @constructor
 */
function GraphGroup(group, groupId, options, groupsUsingDefaultStyles) {
  this.id = groupId;
  var fields = ['sampling', 'style', 'sort', 'yAxisOrientation', 'barChart', 'drawPoints', 'shaded', 'interpolation', 'zIndex','excludeFromStacking', 'excludeFromLegend'];
  this.options = util.selectiveBridgeObject(fields, options);
  this.usingDefaultStyle = group.className === undefined;
  this.groupsUsingDefaultStyles = groupsUsingDefaultStyles;
  this.zeroPosition = 0;
  this.update(group);
  if (this.usingDefaultStyle == true) {
    this.groupsUsingDefaultStyles[0] += 1;
  }
  this.itemsData = [];
  this.visible = group.visible === undefined ? true : group.visible;
}

/**
 * this loads a reference to all items in this group into this group.
 * @param {array} items
 */
GraphGroup.prototype.setItems = function (items) {
  if (items != null) {
    this.itemsData = items;
    if (this.options.sort == true) {
      util.insertSort(this.itemsData,function (a, b) {
        return a.x > b.x ? 1 : -1;
      });
    }
  }
  else {
    this.itemsData = [];
  }
};

GraphGroup.prototype.getItems = function () {
  return this.itemsData;
}

/**
 * this is used for barcharts and shading, this way, we only have to calculate it once.
 * @param pos
 */
GraphGroup.prototype.setZeroPosition = function (pos) {
  this.zeroPosition = pos;
};

/**
 * set the options of the graph group over the default options.
 * @param options
 */
GraphGroup.prototype.setOptions = function (options) {
  if (options !== undefined) {
    var fields = ['sampling', 'style', 'sort', 'yAxisOrientation', 'barChart', 'zIndex','excludeFromStacking', 'excludeFromLegend'];
    util.selectiveDeepExtend(fields, this.options, options);

    // if the group's drawPoints is a function delegate the callback to the onRender property
    if (typeof options.drawPoints == 'function') {
      options.drawPoints = {
        onRender: options.drawPoints
      }
    }

    util.mergeOptions(this.options, options, 'interpolation');
    util.mergeOptions(this.options, options, 'drawPoints');
    util.mergeOptions(this.options, options, 'shaded');

    if (options.interpolation) {
      if (typeof options.interpolation == 'object') {
        if (options.interpolation.parametrization) {
          if (options.interpolation.parametrization == 'uniform') {
            this.options.interpolation.alpha = 0;
          }
          else if (options.interpolation.parametrization == 'chordal') {
            this.options.interpolation.alpha = 1.0;
          }
          else {
            this.options.interpolation.parametrization = 'centripetal';
            this.options.interpolation.alpha = 0.5;
          }
        }
      }
    }
  }
};


/**
 * this updates the current group class with the latest group dataset entree, used in _updateGroup in linegraph
 * @param group
 */
GraphGroup.prototype.update = function (group) {
  this.group = group;
  this.content = group.content || 'graph';
  this.className = group.className || this.className || 'vis-graph-group' + this.groupsUsingDefaultStyles[0] % 10;
  this.visible = group.visible === undefined ? true : group.visible;
  this.style = group.style;
  this.setOptions(group.options);
};

/**
 * return the legend entree for this group.
 *
 * @param iconWidth
 * @param iconHeight
 * @returns {{icon: HTMLElement, label: (group.content|*|string), orientation: (.options.yAxisOrientation|*)}}
 */
GraphGroup.prototype.getLegend = function (iconWidth, iconHeight, framework, x, y) {
  if (framework == undefined || framework == null) {
    var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg");
    framework = {svg: svg, svgElements:{}, options: this.options, groups: [this]}
  }
  if (x == undefined || x == null){
    x = 0;
  }
  if (y == undefined || y == null){
    y = 0.5 * iconHeight;
  }
  switch (this.options.style){
    case "line":
      Lines.drawIcon(this, x, y, iconWidth, iconHeight, framework);
      break;
    case "points": //explicit no break
    case "point":
      Points.drawIcon(this, x, y, iconWidth, iconHeight, framework);
      break;
    case "bar":
      Bars.drawIcon(this, x, y, iconWidth, iconHeight, framework);
      break;
  }
  return {icon: framework.svg, label: this.content, orientation: this.options.yAxisOrientation};
};

GraphGroup.prototype.getYRange = function (groupData) {
  var yMin = groupData[0].y;
  var yMax = groupData[0].y;
  for (var j = 0; j < groupData.length; j++) {
    yMin = yMin > groupData[j].y ? groupData[j].y : yMin;
    yMax = yMax < groupData[j].y ? groupData[j].y : yMax;
  }
  return {min: yMin, max: yMax, yAxisOrientation: this.options.yAxisOrientation};
};

module.exports = GraphGroup;
