'use strict';

var _round = require('lodash/round');

var Chart = require('chart.js');
var defaults = Chart.defaults;
var Element = Chart.Element;
var helpers = Chart.helpers;
var Ticks = Chart.Ticks;
var Tooltip = Chart.Tooltip;
var prices = {entry: [], exit: []};

var KnokLinearScale = (function () {
  function labelsFromTicks(ticks) {
    var labels = [];
    var i, ilen;

    for (i = 0, ilen = ticks.length; i < ilen; ++i) {
      labels.push(ticks[i].label);
    }

    return labels;
  }

  function getLineValue(scale, index, offsetGridLines) {
    var lineValue = scale.getPixelForTick(index);

    if (offsetGridLines) {
      if (index === 0) {
        lineValue -= (scale.getPixelForTick(1) - lineValue) / 2;
      } else {
        lineValue -= (lineValue - scale.getPixelForTick(index - 1)) / 2;
      }
    }
    return lineValue;
  }

  function computeTextSize(context, tick, font) {
    return helpers.isArray(tick) ?
      helpers.longestText(context, font, tick) :
      context.measureText(tick).width;
  }

  function parseFontOptions(options) {
    var valueOrDefault = helpers.valueOrDefault;
    var globalDefaults = defaults.global;
    var size = valueOrDefault(options.fontSize, globalDefaults.defaultFontSize);
    var style = valueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle);
    var family = valueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily);

    return {
      size: size,
      style: style,
      family: family,
      font: helpers.fontString(size, style, family)
    };
  }

  function parseLineHeight(options) {
    return helpers.options.toLineHeight(
      helpers.valueOrDefault(options.lineHeight, 1.2),
      helpers.valueOrDefault(options.fontSize, defaults.global.defaultFontSize));
  }

  return Chart.LinearScaleBase.extend({

    initToolTip: function() {
			var me = this;
			me.tooltip = new Tooltip({
				_chart: me,
				_chartInstance: me, // deprecated, backward compatibility
				_data: me.data,
				_options: me.options.tooltips
			}, me);
    },
    
    convertTicksToLabels: function(ticks)
    {
      var me = this;
			me.ticksAsNumbers = me.ticks.slice();
			// me.zeroLineIndex = me.ticks.indexOf(0);

      // Chart.Scale.prototype.convertTicksToLabels.call(me);
      var labels = [];
      for(var i = 0; i < this.ticks.length; i++) {
        labels.push(this.ticks[i].toString());
      }
      return labels;
    },

    buildTicks: function () {
      // console.warn(this);
      var digits = this.options.ticks.hasOwnProperty('digits') ? this.options.ticks.digits : 8;
      
      this.exitPriceFrom = _round(this.options.ticks.exitPriceFrom, digits);
      this.exitPriceTo = _round(this.options.ticks.exitPriceTo, digits);

      this.entryPriceFrom = _round(this.options.ticks.entryPriceFrom, digits);
      this.entryPriceTo = _round(this.options.ticks.entryPriceTo, digits);

      this.stopLoss = _round(this.options.ticks.stopLoss, digits);

      this.entryPriceCentred = _round(this.entryPriceFrom + (this.entryPriceTo - this.entryPriceFrom) / 2, digits);
      this.exitPriceCentred = _round(this.exitPriceFrom + (this.exitPriceTo - this.exitPriceFrom) / 2, digits);
      this.lowMidCentred = _round(this.stopLoss + (this.entryPriceFrom  - this.stopLoss) / 2, digits);
      this.highMidCentred = _round(this.entryPriceTo + (this.exitPriceFrom - this.entryPriceTo) / 2, digits);

      this.min = this.options.ticks.min ? this.options.ticks.min : this.stopLoss;
      this.max = this.exitPriceTo;

      this.ticks = [this.stopLoss, this.lowMidCentred, this.entryPriceFrom, this.entryPriceCentred, this.entryPriceTo, this.highMidCentred, this.exitPriceFrom, this.exitPriceCentred, this.exitPriceTo];
      
      if (this.options.position === "left" || this.options.position === "right") {
        // We are in a vertical orientation. The top value is the highest. So reverse the array
        this.ticks.reverse();
      }

      if (this.options.ticks.reverse) {
        this.ticks.reverse();

        this.start = this.max;
        this.end = this.min;
      } else {
        this.start = this.min;
        this.end = this.max;
      }

      this.zeroLineIndex = this.ticks.indexOf(0);
    },

    getLabelForIndex: function (index, datasetIndex, force) {
      if (!helpers.isNullOrUndef(force)) {
        if (force == 'x' || force == 'y') {
          return +this.getRightValue(this.chart.config.data.datasets[datasetIndex].data[index][force]);
        }
      }
      return +this.getRightValue(this.chart.config.data.datasets[datasetIndex].data[index]);
    },

    // Utils
    getPixelForValue: function (value) {
      // This must be called after fit has been run so that
      // this.left, this.top, this.right, and this.bottom have been defined
      var that = this;
      var start = that.start;

      var rightValue = +that.getRightValue(value);
      var pixel;
      var range = that.end - start;

      if (that.isHorizontal()) {
        pixel = that.left + (that.width / range * (rightValue - start));
      } else {
        pixel = that.bottom - (that.height / range * (rightValue - start));
      }
      var range1 = this.entryPriceFrom - this.stopLoss;
      var range2 = this.exitPriceFrom - this.entryPriceTo;
      
      if (range1 < range2) {
        if (rightValue > this.stopLoss && rightValue < this.entryPriceFrom) {
          pixel = pixel / 2 + pixel / 3 + 6;
        }
        else if (rightValue >= this.entryPriceFrom && rightValue <= this.entryPriceTo) {
          pixel = pixel / 2 + pixel / 4 + 3;
        }
        else if (rightValue > this.entryPriceTo && rightValue < this.exitPriceFrom) {
          pixel = pixel / 2 + pixel / 3 + 1;
        }
      } else {
        if (rightValue > this.stopLoss && rightValue < this.entryPriceFrom) {
          pixel = pixel / 2 + pixel / 3 + 1;
        }
        else if (rightValue >= this.entryPriceFrom && rightValue <= this.entryPriceTo) {
          pixel = pixel / 2 + pixel / 4 + 3;
        }
        else if (rightValue > this.entryPriceTo && rightValue < this.exitPriceFrom) {
          pixel = pixel / 2 + pixel / 3 + 6;
        }
      } 
      return pixel;
    },

    getValueForPixel: function (pixel) {
      var that = this;
      var isHorizontal = that.isHorizontal();
      var innerDimension = isHorizontal ? that.width : that.height;
      var offset = (isHorizontal ? pixel - that.left : that.bottom - pixel) / innerDimension;
      return that.start + ((that.end - that.start) * offset);
    },

    getPixelForTick: function (index) {
      return +this.getPixelForValue(this.ticksAsNumbers[index]);
    },

    addDrawItem(chartArea, tick, index, itemsToDraw) {
      var that = this;
      var options = that.options;
      var gridLines = options.gridLines;
      var optionTicks = options.ticks.minor;
      var label = tick.label;
      var lineWidth, lineColor, borderDash, borderDashOffset;
      var globalDefaults = defaults.global;

      var tl = gridLines.drawTicks ? gridLines.tickMarkLength : 0;
      var isHorizontal = that.isHorizontal();
      var labelRotationRadians = helpers.toRadians(that.labelRotation);

      var axisWidth = that.options.gridLines.lineWidth;
      var xTickStart = options.position === 'right' ? that.right : that.right - axisWidth - tl;
      var xTickEnd = options.position === 'right' ? that.right + tl : that.right;
      var yTickStart = options.position === 'bottom' ? that.top + axisWidth : that.bottom - tl - axisWidth;
      var yTickEnd = options.position === 'bottom' ? that.top + axisWidth + tl : that.bottom + axisWidth;

        if (index === that.zeroLineIndex && options.offset === gridLines.offsetGridLines) {
          // Draw the first index specially
          lineWidth = gridLines.zeroLineWidth;
          lineColor = gridLines.zeroLineColor;
          borderDash = gridLines.zeroLineBorderDash;
          borderDashOffset = gridLines.zeroLineBorderDashOffset;
        } else {
          lineWidth = helpers.valueAtIndexOrDefault(gridLines.lineWidth, index);
          lineColor = helpers.valueAtIndexOrDefault(gridLines.color, index);
          borderDash = helpers.valueOrDefault(gridLines.borderDash, globalDefaults.borderDash);
          borderDashOffset = helpers.valueOrDefault(gridLines.borderDashOffset, globalDefaults.borderDashOffset);
        }

        // Common properties
        var tx1, ty1, tx2, ty2, x1, y1, x2, y2, labelX, labelY;
        var textAlign = 'middle';
        var textBaseline = 'middle';
        var tickPadding = optionTicks.padding;

        if (isHorizontal) {
          var labelYOffset = tl + tickPadding;

          if (options.position === 'bottom') {
            // bottom
            textBaseline = !isRotated ? 'top' : 'middle';
            textAlign = !isRotated ? 'center' : 'right';
            labelY = that.top + labelYOffset;
          } else {
            // top
            textBaseline = !isRotated ? 'bottom' : 'middle';
            textAlign = !isRotated ? 'center' : 'left';
            labelY = that.bottom - labelYOffset;
          }

          var xLineValue = getLineValue(that, index, gridLines.offsetGridLines && ticks.length > 1);
          if (xLineValue < that.left) {
            lineColor = 'rgba(0,0,0,0)';
          }
          xLineValue += helpers.aliasPixel(lineWidth);

          labelX = that.getPixelForTick(index) + optionTicks.labelOffset; // x values for optionTicks (need to consider offsetLabel option)

          tx1 = tx2 = x1 = x2 = xLineValue;
          ty1 = yTickStart;
          ty2 = yTickEnd;
          y1 = chartArea.top;
          y2 = chartArea.bottom + axisWidth;
        } else {
          var isLeft = options.position === 'left';
          var labelXOffset;

          if (optionTicks.mirror) {
            textAlign = isLeft ? 'left' : 'right';
            labelXOffset = tickPadding;
          } else {
            textAlign = isLeft ? 'right' : 'left';
            labelXOffset = tl + tickPadding;
          }

          labelX = isLeft ? that.right - labelXOffset : that.left + labelXOffset;

          var yLineValue = getLineValue(that, index, gridLines.offsetGridLines && ticks.length > 1);
          if (yLineValue < that.top) {
            lineColor = 'rgba(0,0,0,0)';
          }
          yLineValue += helpers.aliasPixel(lineWidth);

          labelY = that.getPixelForTick(index) + optionTicks.labelOffset;

          tx1 = xTickStart;
          tx2 = xTickEnd;
          x1 = chartArea.left;
          x2 = chartArea.right + axisWidth;
          ty1 = ty2 = y1 = y2 = yLineValue;
        }
        var digits = options.ticks.hasOwnProperty('digits') ? options.ticks.digits : 8;
        var roundedLabel = _round(label, digits);
        if (roundedLabel == that.entryPriceFrom || roundedLabel == that.entryPriceTo) {
          that.prices.entry.push({
            tx1: tx1,
            ty1: ty1,
            tx2: tx2,
            ty2: ty2,
            x1: x1,
            y1: y1,
            x2: x2,
            y2: y2,
            labelX: labelX,
            labelY: labelY,
            glWidth: lineWidth,
            glColor: lineColor,
            glBorderDash: borderDash,
            glBorderDashOffset: borderDashOffset,
            rotation: -1 * labelRotationRadians,
            label: roundedLabel,
            major: tick.major,
            textBaseline: textBaseline,
            textAlign: textAlign
          });
          if (roundedLabel == that.entryPriceCentred) {
            itemsToDraw.push({
              tx1: tx1,
              ty1: ty1,
              tx2: tx2,
              ty2: ty2,
              x1: x1,
              y1: y1,
              x2: x2,
              y2: y2,
              labelX: labelX,
              labelY: labelY,
              glWidth: lineWidth,
              glColor: lineColor,
              glBorderDash: borderDash,
              glBorderDashOffset: borderDashOffset,
              rotation: -1 * labelRotationRadians,
              label: roundedLabel,
              major: tick.major,
              textBaseline: textBaseline,
              textAlign: textAlign
            });
          }
          if (roundedLabel == that.highMidCentred) {
            itemsToDraw.push({
              tx1: tx1,
              ty1: ty1,
              tx2: tx2,
              ty2: ty2,
              x1: x1,
              y1: y1,
              x2: x2,
              y2: y2,
              labelX: labelX,
              labelY: labelY,
              glWidth: lineWidth,
              glColor: lineColor,
              glBorderDash: borderDash,
              glBorderDashOffset: borderDashOffset,
              rotation: -1 * labelRotationRadians,
              label: roundedLabel,
              major: tick.major,
              textBaseline: textBaseline,
              textAlign: textAlign
            });
          }
        } else if (roundedLabel == that.exitPriceFrom || roundedLabel == that.exitPriceTo) {
          that.prices.exit.push({
            tx1: tx1,
            ty1: ty1,
            tx2: tx2,
            ty2: ty2,
            x1: x1,
            y1: y1,
            x2: x2,
            y2: y2,
            labelX: labelX,
            labelY: labelY,
            glWidth: lineWidth,
            glColor: lineColor,
            glBorderDash: borderDash,
            glBorderDashOffset: borderDashOffset,
            rotation: -1 * labelRotationRadians,
            label: roundedLabel,
            major: tick.major,
            textBaseline: textBaseline,
            textAlign: textAlign
          });
          if (roundedLabel == that.exitPriceCentred) {
            itemsToDraw.push({
              tx1: tx1,
              ty1: ty1,
              tx2: tx2,
              ty2: ty2,
              x1: x1,
              y1: y1,
              x2: x2,
              y2: y2,
              labelX: labelX,
              labelY: labelY,
              glWidth: lineWidth,
              glColor: lineColor,
              glBorderDash: borderDash,
              glBorderDashOffset: borderDashOffset,
              rotation: -1 * labelRotationRadians,
              label: roundedLabel,
              major: tick.major,
              textBaseline: textBaseline,
              textAlign: textAlign
            });
          }
        } else {
          itemsToDraw.push({
            tx1: tx1,
            ty1: ty1,
            tx2: tx2,
            ty2: ty2,
            x1: x1,
            y1: y1,
            x2: x2,
            y2: y2,
            labelX: labelX,
            labelY: labelY,
            glWidth: lineWidth,
            glColor: lineColor,
            glBorderDash: borderDash,
            glBorderDashOffset: borderDashOffset,
            rotation: -1 * labelRotationRadians,
            label: roundedLabel,
            major: tick.major,
            textBaseline: textBaseline,
            textAlign: textAlign
          });
        }
    },

    formatPrice: function (price, precision) {
      if(!precision) {
        precision = 8;
      }
      var arr = price.toString().split('.');
      var arr1 = '';
      if (arr.length > 1) {
        arr1 = arr[1];
      } 
      while(arr1.length < precision) {
        arr1 += '0';
      }
      return arr[0] + '.' + arr1;
    },

    fit: function() {
      var that = this;
      // Reset
      var tickOffset = 60;
      var minSize = that.minSize = {
        width: 0,
        height: 0
      };

      var labels = labelsFromTicks(that._ticks);

      var opts = that.options;
      var tickOpts = opts.ticks;
      var scaleLabelOpts = opts.scaleLabel;
      var gridLineOpts = opts.gridLines;
      var display = opts.display;
      var isHorizontal = that.isHorizontal();

      var tickFont = parseFontOptions(tickOpts);
      var tickMarkLength = opts.gridLines.tickMarkLength;

      // Width
      if (isHorizontal) {
        // subtract the margins to line up with the chartArea if we are a full width scale
        minSize.width = that.isFullWidth() ? that.maxWidth - that.margins.left - that.margins.right : that.maxWidth;
      } else {
        minSize.width = display && gridLineOpts.drawTicks ? tickMarkLength : 0;
      }

      // height
      if (isHorizontal) {
        minSize.height = display && gridLineOpts.drawTicks ? tickMarkLength * 2 : 0;
      } else {
        minSize.height = that.maxHeight; // fill all the height
      }

      // Are we showing a title for the scale?
      if (scaleLabelOpts.display && display) {
        var scaleLabelLineHeight = parseLineHeight(scaleLabelOpts);
        var scaleLabelPadding = helpers.options.toPadding(scaleLabelOpts.padding);
        var deltaHeight = scaleLabelLineHeight + scaleLabelPadding.height;

        if (isHorizontal) {
          minSize.height += deltaHeight;
        } else {
          minSize.width += deltaHeight;
        }
      }

      // Don't bother fitting the ticks if we are not showing them
      if (tickOpts.display && display) {
        var largestTextWidth = helpers.longestText(that.ctx, tickFont.font, labels, that.longestTextCache);
        var tallestLabelHeightInLines = helpers.numberOfLabelLines(labels);
        var lineSpace = tickFont.size * 0.5;
        var tickPadding = that.options.ticks.padding + tickOffset;

        if (isHorizontal) {
          // A horizontal axis is more constrained by the height.
          that.longestLabelWidth = largestTextWidth;

          var angleRadians = helpers.toRadians(that.labelRotation);
          var cosRotation = Math.cos(angleRadians);
          var sinRotation = Math.sin(angleRadians);

          // TODO - improve this calculation
          var labelHeight = (sinRotation * largestTextWidth)
            + (tickFont.size * tallestLabelHeightInLines)
            + (lineSpace * (tallestLabelHeightInLines - 1))
            + lineSpace; // padding

          minSize.height = Math.min(that.maxHeight, minSize.height + labelHeight + tickPadding);

          that.ctx.font = tickFont.font;
          var firstLabelWidth = computeTextSize(that.ctx, labels[0], tickFont.font);
          var lastLabelWidth = computeTextSize(that.ctx, labels[labels.length - 1], tickFont.font);

          // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned
          // which means that the right padding is dominated by the font height
          if (that.labelRotation !== 0) {
            that.paddingLeft = opts.position === 'bottom' ? (cosRotation * firstLabelWidth) + 3 : (cosRotation * lineSpace) + 3; // add 3 px to move away from canvas edges
            that.paddingRight = opts.position === 'bottom' ? (cosRotation * lineSpace) + 3 : (cosRotation * lastLabelWidth) + 3;
          } else {
            that.paddingLeft = firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges
            that.paddingRight = lastLabelWidth / 2 + 3;
          }
        } else {
          // A vertical axis is more constrained by the width. Labels are the
          // dominant factor here, so get that length first and account for padding
          if (tickOpts.mirror) {
            largestTextWidth = 0;
          } else {
            // use lineSpace for consistency with horizontal axis
            // tickPadding is not implemented for horizontal
            largestTextWidth += tickPadding + lineSpace;
          }

          minSize.width = Math.min(that.maxWidth, minSize.width + largestTextWidth);

          that.paddingTop = tickFont.size / 2 + 1;
          that.paddingBottom = tickFont.size / 2 + 1;
        }
      }

      that.handleMargins();

      that.width = minSize.width;
      that.height = minSize.height;
    },

    draw: function (chartArea) {
      // console.warn(chartArea);

      var that = this;
      var options = that.options;
      that.chart.pricesTicks = [];
      var pricesTicks = that.chart.pricesTicks;
      if (!options.display) {
        return;
      }

      var context = that.ctx;
      var globalDefaults = defaults.global;
      var optionTicks = options.ticks.minor;
      var optionMajorTicks = options.ticks.major || optionTicks;
      var gridLines = options.gridLines;
      var scaleLabel = options.scaleLabel;

      // var isRotated = that.labelRotation !== 0;
      var isHorizontal = that.isHorizontal();

      var ticks = optionTicks.autoSkip ? that._autoSkip(that.getTicks()) : that.getTicks();
      var tickFontColor = helpers.valueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor);
      var tickFont = parseFontOptions(optionTicks);
      var majorTickFontColor = helpers.valueOrDefault(optionMajorTicks.fontColor, globalDefaults.defaultFontColor);
      var majorTickFont = parseFontOptions(optionMajorTicks);

      var scaleLabelFontColor = helpers.valueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor);
      var scaleLabelFont = parseFontOptions(scaleLabel);
      var scaleLabelPadding = helpers.options.toPadding(scaleLabel.padding);

      var itemsToDraw = [];
      var axisWidth = that.options.gridLines.lineWidth;

      that.prices = {entry: [], exit: []};

      if (helpers.isNullOrUndef(context) || helpers.isNullOrUndef(context.canvas)) {
        return;
      }

      helpers.each(ticks, function (tick, index) {
        // autoskipper skipped this tick (#4635)
        if (helpers.isNullOrUndef(tick.label)) {
          return;
        }

        that.addDrawItem(chartArea, tick, index, itemsToDraw);
      });

      //Draw gradient range rect
      if (!helpers.isNullOrUndef(context) && !helpers.isNullOrUndef(context.canvas)) {
        var grayedOut = options.ticks.hasOwnProperty('grayedOut') ? options.ticks.grayedOut : false;
        if (!options.listItemMode && that.prices.exit.length) {
          var exitFrom = that.prices.exit[0];
          var exitTo = that.prices.exit[1];
          // console.warn([exitFrom, exitTo]);

          var gradient = context.createLinearGradient(exitFrom.x1, 0, exitTo.x2, 0);
          var gradientColor = grayedOut ? 'rgba(151, 151, 151, 0.15)' : 'rgba(33, 222, 171, 0.15)';
          var gradientColorStop = grayedOut ? 'rgba(151, 151, 151, 0)' : 'rgba(33, 222, 171, 0)';
          if (options.position === 'right') {
            gradient.addColorStop(0, gradientColorStop);
            gradient.addColorStop(1, gradientColor);
          } else {
            gradient.addColorStop(0, gradientColor);
            gradient.addColorStop(1, gradientColorStop);
          }

          context.save();
          context.beginPath();
          context.lineWidth = exitFrom.glWidth || exitTo.glWidth;
          context.fillStyle = gradient;
          context.fillRect(exitFrom.x1, exitFrom.y1 - context.lineWidth, exitTo.x2 - 20, exitTo.y2 - exitFrom.y2 + context.lineWidth);
          context.closePath();
          context.restore();
        }

        if (!options.listItemMode && that.prices.entry.length) {
          var entryFrom = that.prices.entry[0];
          var entryTo = that.prices.entry[1];
          // console.warn([entryFrom, entryTo]);

          var gradient = context.createLinearGradient(entryFrom.x1, 0, entryTo.x2, 0);
          var gradientColor = grayedOut ? 'rgba(151, 151, 151, 0.15)' : 'rgba(0, 186, 255, 0.15)';
          var gradientColorStop = grayedOut ? 'rgba(151, 151, 151, 0)' : 'rgba(0, 186, 255, 0)';
          if (options.position === 'right') {
            gradient.addColorStop(0, gradientColorStop);
            gradient.addColorStop(1, gradientColor);
          } else {
            gradient.addColorStop(0, gradientColor);
            gradient.addColorStop(1, gradientColorStop);
          }

          context.save();
          context.beginPath();
          context.lineWidth = entryFrom.glWidth || entryTo.glWidth;
          context.fillStyle = gradient;
          context.fillRect(entryFrom.x1, entryFrom.y1 - context.lineWidth, entryTo.x2 - 20, entryTo.y2 - entryFrom.y2 + context.lineWidth);
          context.closePath();
          context.restore();
        }
      }

      // Draw all of the tick labels, tick marks, and grid lines at the correct places
      helpers.each(itemsToDraw, function (itemToDraw) {
        var digits = options.ticks.hasOwnProperty('digits') ? options.ticks.digits : 8;
        var grayedOut = options.ticks.hasOwnProperty('grayedOut') ? options.ticks.grayedOut : false;
        var roundedLabel = _round(itemToDraw.label, digits);
        var mess = null;

        if (gridLines.display) {
          context.save();
          context.lineWidth = itemToDraw.glWidth;
          var drawSL =  roundedLabel == that.stopLoss;
          var drawEntry =  roundedLabel == that.entryPriceCentred;
          var drawExit =  roundedLabel == that.exitPriceCentred;

          var tickColor = itemToDraw.glColor;
          if (drawSL) {
            tickColor = '#ff544d';
          } else if (drawExit) {
            tickColor = '#21deab';
          } else if (drawEntry) {
            tickColor = '#00baff';
          }
        
          // Draw ranges lines
          if (drawEntry || drawSL || drawExit) {
            context.strokeStyle = grayedOut ? '#979797' : tickColor;

            if (context.setLineDash && drawSL) {
              context.setLineDash([4, 4]);
              context.lineDashOffset = 0;
            } else if (context.setLineDash) {
              context.setLineDash(itemToDraw.glBorderDash);
              context.lineDashOffset = itemToDraw.glBorderDashOffset;
            }
            context.beginPath();

            if (!options.listItemMode && gridLines.drawTicks) {
              context.moveTo(itemToDraw.tx1, itemToDraw.ty1);
              context.lineTo(itemToDraw.tx2, itemToDraw.ty2);
            }

            if (gridLines.drawOnChartArea) {
              if (options.position === 'right') {
                context.moveTo(itemToDraw.x1, itemToDraw.y1);
              } else {
                context.moveTo(itemToDraw.x1 + 8, itemToDraw.y1);
              }
              context.lineTo(itemToDraw.x2, itemToDraw.y2);
            }
            context.stroke();
            context.closePath();
            context.save();

            // Reset stroke dash
            context.setLineDash([]);
            context.save();
          }

          // Draw round marks on Y axis
          if (drawSL || drawEntry || drawExit) {
            if (options.position === 'right') {
              var y = itemToDraw.ty2 - (itemToDraw.ty2 - itemToDraw.ty1) / 2;
              // context.beginPath();
              // context.fillStyle = '#ffffff';
              // context.arc(itemToDraw.x2 + 8, y, 7, 0, 2 * Math.PI, false);
              // context.fill();
              // context.closePath();
              // context.save();
              // context.restore();

              context.beginPath();
              context.fillStyle = tickColor;
              context.arc(itemToDraw.x2 + 8, y, 6, 0, 2 * Math.PI, false);
              context.fill();
              context.closePath();
              context.save();
              
              pricesTicks.push({x: itemToDraw.x2, y: y, label: that.formatPrice(itemToDraw.label, optionTicks.precision)});
            } else {
              var y = itemToDraw.ty2 - (itemToDraw.ty2 - itemToDraw.ty1) / 2;
              // context.beginPath();
              // context.fillStyle = '#ffffff';
              // context.arc(itemToDraw.x1, y, 6, 0, 2 * Math.PI, false);
              // context.fill();
              // context.closePath();
              // context.save();
              // context.restore();

              context.beginPath();
              context.fillStyle = tickColor;
              context.arc(itemToDraw.x1, y, 5, 0, 2 * Math.PI, false);
              context.fill();
              context.closePath();
              context.save();
            }
          }
          // context.strokeStyle = tickColor;    
          // context.stroke();
          context.restore();
        }

        if (optionTicks.display) {
          // Make sure we draw text in the correct color and font
          context.save();
          context.translate(itemToDraw.labelX, itemToDraw.labelY);
          context.rotate(itemToDraw.rotation);
          context.font = itemToDraw.major ? majorTickFont.font : tickFont.font;
          context.textBaseline = itemToDraw.textBaseline;
          context.textAlign = itemToDraw.textAlign;
          
          if (!drawSL && !drawEntry && !drawExit) {
            tickColor = itemToDraw.major ? majorTickFontColor : tickFontColor;
          }
          context.fillStyle = tickColor;

          if (!options.listItemMode) {
            if (drawSL) {
              mess = 'Stop Loss';
            } else if (drawExit) {
              mess = 'Exit';
            } else if (drawEntry) {
              mess = 'Entry';
            }
            context.fillStyle = tickColor;

            // Add labels to draw
            if (drawExit && that.prices.exit.length) {
              var exitFrom = that.prices.exit[0];
              var exitTo = that.prices.exit[1];
              var label = [exitFrom.label, exitTo.label];
            } else if (drawEntry && that.prices.entry.length) {
                var entryFrom = that.prices.entry[0];
                var entryTo = that.prices.entry[1];
                var label = [entryFrom.label, entryTo.label];
            } else {
              var label = itemToDraw.label;
            }
          } else {
            // Add labels to draw
            var label = itemToDraw.label;
          }

          // Draw labels
          if (!options.listItemMode && (drawEntry || drawExit || drawSL)) {
            var isLeft = options.position === 'left';
            var distFromLine = 0; // (tickFont.size  / 2 * 1.5);
            if (helpers.isArray(label)) {
              var lineCount = label.length;
              var lineHeight = tickFont.size * 1.5;
              var labelSize = 1;
              var y = that.isHorizontal() ? 0 : -lineHeight * (lineCount - 1) / 2;

              // for (var i = 0; i < lineCount; ++i) {
              //   const formattedLabel = that.formatPrice(label[i], optionTicks.precision);
              //   var ls = (formattedLabel.length > 0) ? formattedLabel.length - 1 : 1;
              //   if (ls > labelSize) {
              //     labelSize = ls;
              //   }
              //   // We just make sure the multiline element is a string here..
              //   context.fillText('' + formattedLabel, isLeft ? 0 : 8, y);
              //   // apply same lineSpacing as calculated @ L#320
              //   y += lineHeight;
              // }

              if (mess != null) {
                //Draw label above line
                context.fillText(mess, labelSize * tickFont.size * 0.8, isLeft ? 0 : -distFromLine);
              }
            } else {
              const formattedLabel = that.formatPrice(label, optionTicks.precision);
              var labelSize = 1; // (formattedLabel.length > 0) ? formattedLabel.length - 1 : 1;
              if(drawSL) {
                //Draw label above line
                // context.fillText(formattedLabel, isLeft ? 0 : 8, isLeft ? 0 : -distFromLine);
                if (mess != null) {
                  context.fillText(mess, labelSize * tickFont.size * 0.8, isLeft ? 0 : -distFromLine);
                }
              } else {
                //Draw label below line
                // context.fillText(formattedLabel, isLeft ? 0 : 8, isLeft ? 0 : distFromLine);
                if (mess != null) {
                  context.fillText(mess, labelSize * tickFont.size * 0.8, isLeft ? 0 : distFromLine);
                }
              }
            }
            //Draw line range divider 
            // if (!isLeft) {
            //   context.moveTo(8, 0);
            //   context.lineTo(labelSize * tickFont.size * 0.8 - 8, 0);
            //   context.strokeStyle = itemToDraw.glColor;
            //   context.stroke();
            // }
          }
          context.restore();  
        }
      });

      if (scaleLabel.display) {
        // Draw the scale label
        var scaleLabelX;
        var scaleLabelY;
        var rotation = 0;
        var halfLineHeight = parseLineHeight(scaleLabel) / 2;

        if (isHorizontal) {
          scaleLabelX = that.left + ((that.right - that.left) / 2); // midpoint of the width
          scaleLabelY = options.position === 'bottom'
            ? that.bottom - halfLineHeight - scaleLabelPadding.bottom
            : that.top + halfLineHeight + scaleLabelPadding.top;
        } else {
          var isLeft = options.position === 'left';
          scaleLabelX = isLeft
            ? that.left + halfLineHeight + scaleLabelPadding.top
            : that.right - halfLineHeight - scaleLabelPadding.top;
          scaleLabelY = that.top + ((that.bottom - that.top) / 2);
          rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI;
        }

        context.save();
        context.translate(scaleLabelX, scaleLabelY);
        context.rotate(rotation);
        context.textAlign = 'center';
        context.textBaseline = 'middle';
        context.fillStyle = scaleLabelFontColor; // render in correct colour
        context.font = scaleLabelFont.font;
        context.fillText(scaleLabel.labelString, 0, 0);
        context.restore();
      }

      if (gridLines.drawBorder) {
        // Draw the line at the edge of the axis
        context.lineWidth = helpers.valueAtIndexOrDefault(gridLines.lineWidth, 0);
        context.strokeStyle = helpers.valueAtIndexOrDefault(gridLines.color, 0);
        var x1 = that.left;
        var x2 = that.right + axisWidth;
        var y1 = that.top;
        var y2 = that.bottom + axisWidth;

        var aliasPixel = helpers.aliasPixel(context.lineWidth);
        if (isHorizontal) {
          y1 = y2 = options.position === 'top' ? that.bottom : that.top;
          y1 += aliasPixel;
          y2 += aliasPixel;
        } else {
          x1 = x2 = options.position === 'left' ? that.right : that.left;
          x1 += aliasPixel;
          x2 += aliasPixel;
        }

        context.beginPath();
        context.moveTo(x1, y1);
        context.lineTo(x2, y2);
        context.stroke();
      }
    }
  });
})();

var exports = module.exports = {};
exports.KnokLinearScale = KnokLinearScale;
