"use strict";

CanvasRenderingContext2D.prototype.line = function (x1, y1, x2, y2, color, width) {
   this.beginPath();
   this.moveTo(x1, y1);
   this.lineTo(x2, y2);
   this.strokeStyle = color;
   this.lineWidth = width;
   this.stroke();
}


var UrsSlidingScale = function (canvas, parameters) {
   var context = (undefined === parameters.context ? null : parameters.context),
       height = (undefined === parameters.height ? 0 : parameters.height),
       width = (undefined === parameters.width ? 0 : parameters.width),
       top = (undefined === parameters.top ? 0 : parameters.top),
       left = (undefined === parameters.left ? 0 : parameters.left),
       resize = (undefined === parameters.resize ? false : parameters.true),
       scaleRange = (undefined === parameters.scaleRange ? 100 : parameters.scaleRange),
       largeTicksCount = (undefined === parameters.largeTicksCount ? 5 : parameters.largeTicksCount),
       smallTicksCount = (undefined === parameters.smallTicksCount ? 4 : parameters.smallTicksCount),
       largeTicksLength = (undefined === parameters.largeTicksLength ? 15 : parameters.largeTicksLength),
       smallTicksLength = (undefined === parameters.smallTicksLength ? 10 : parameters.smallTicksLength),
       scaleColor = (undefined === parameters.scaleColor ? '#000000' : parameters.scaleColor),
       value = (undefined === parameters.value ? 0 : parameters.value),
       //
       initialized = false,
       backgroundContext, // Grauer Gradient-Hintergrund
       backgroundBuffer,
       scaleContext,      // Skala
       scaleBuffer,
       foregroundContext, // Rahmen & Nadel
       foregroundBuffer,
       ctx;
   // End of variables

   // Get the canvas context and clear it
   if (context) {
      ctx = context;
   } else {
      ctx = getCanvasContext(canvas);
   }

   // Has a height been specified?
   if (height === 0) {
      height = ctx.canvas.height;
   }
   if (width === 0) {
      width = ctx.canvas.width;
   }

   // Resize and clear the main context
   if (resize) {
      ctx.canvas.width = width;
      ctx.canvas.height = height;
   }

   var Wm = width / 2;
   var Hm = height / 2;

   foregroundBuffer = createBuffer(width, height);
   foregroundContext = foregroundBuffer.getContext('2d');
   backgroundBuffer = createBuffer(width, height);
   backgroundContext = backgroundBuffer.getContext('2d');

   function init() {
      initialized = true;
      // Hintergrund zeichnen
      var grd = backgroundContext.createLinearGradient(0, 0, width, 0);
      grd.addColorStop(0.000, 'rgb(110, 110, 110)');
      grd.addColorStop(0.500, 'rgb(210, 210, 210)');
      grd.addColorStop(1.000, 'rgb(110, 110, 110)');
      backgroundContext.fillStyle = grd;
      backgroundContext.fillRect(0, 0, width, height);

      // Vordergrund zeichnen
      foregroundContext.line(0.5, 0.5, width, 0.5, "#A0A0A0", 1); // oben
      foregroundContext.line(0.5, 0.5, 0.5, height, "#A0A0A0", 1); // links
      foregroundContext.line(1.5, 1.5, width, 1.5, "#696969", 1); // oben 2.
      foregroundContext.line(1.5, 1.5, 1.5, height, "#696969", 1); // links 2.
      foregroundContext.line(0, height - 0.5, width, height - 0.5, "#FFFFFF", 1); // unten
      foregroundContext.line(width - 0.5, 0, width - 0.5, height - 0.5, "#FFFFFF", 1); //rechts
      foregroundContext.line(1, height - 1.5, width - 1, height - 1.5, "#E3E3E3", 1); // unten 2.
      foregroundContext.line(width - 1.5, 0.5, width - 1.5, height - 1.5, "#E3E3E3", 1); //rechts 2.
      // Draw scale needle
      foregroundContext.line(Wm, 2, Wm, height - 2, "#FF0000", 2);
   }

   this.repaint = function () {
      if (!initialized) {
         init();
      }
      ctx.drawImage(backgroundBuffer, left, top);
      drawScale();
      ctx.drawImage(scaleBuffer, left, top);
      ctx.drawImage(foregroundBuffer, left, top);
   }; // repaint

   function drawScale () {
      scaleBuffer = createBuffer(width, height);
      scaleContext = scaleBuffer.getContext('2d');
      // Calculate distances between ticks
      var largeTicksDistance = scaleRange / largeTicksCount;
      var smallTicksDistance = largeTicksDistance / (smallTicksCount + 1);

      // Calculate number of pixel between small ticks
      var smallTicksPixels = (width / scaleRange * smallTicksDistance); // 4 Pixel Rand

      // Calculate first large tick value and position
      var tickValue = Math.floor((value - scaleRange / 2) / largeTicksDistance) * largeTicksDistance;
      var tickPosition = Math.floor(Wm - width / scaleRange * (value - tickValue));


      // For all large ticks
      for (var L = 0; L <= largeTicksCount; L++) {
         // Draw large tick
         if (tickValue >= 0)
            scaleContext.line(tickPosition, 0, tickPosition, largeTicksLength, scaleColor, 2);

         scaleContext.fillStyle = scaleColor;
         scaleContext.font = 'bold 18px sans-serif';
         scaleContext.textAlign = 'center';
         if (tickValue >= 0)
            scaleContext.fillText("" + tickValue, tickPosition, (height + largeTicksLength) / 2);

         // For all small ticks
         for (var S = 1; S <= smallTicksCount; S++) {
            // Update tick value and position
            tickValue += smallTicksDistance;
            tickPosition += smallTicksPixels;

            // Draw small tick
            if (tickValue >= 0 && tickPosition < width && tickPosition >0 )
               scaleContext.line(tickPosition, 0, tickPosition, smallTicksLength, scaleColor, 1);
         } // for S

         // Update tick value and position
         tickValue += smallTicksDistance;
         tickPosition += smallTicksPixels;
      } // for L
   } // drawscale


   function createBuffer(width, height) {
      var buffer = document.createElement('canvas');
      buffer.width = width;
      buffer.height = height;
      return buffer;
   } // createBuffer

   function getCanvasContext(elementOrId) {
      var element = (typeof elementOrId === 'string' || elementOrId instanceof String) ?
          document.getElementById(elementOrId) : elementOrId;
      return element.getContext('2d');
   } // getCanvasContext


   // Legt den aktuellen Anzeigewert fest und zeichnet das Control neu
   this.setValue = function (newVal) {
      value = parseFloat(newVal);
      this.repaint();
      return this;
   };

   // Ruft den aktuellen Anzeigewert ab
   this.getValue = function () {
      return value;
   };


  this.repaint();
}