text: /* global $, describe, it, xit, after, beforeEach, afterEach, expect, jasmine, spyOn */
  /* jshint browser: true*/
  
  describe('Flot cursors', function () {
      'use strict';
  
      var sampledata = [[0, 1], [1, 1.1], [2, 1.2]];
      var plot;
      var placeholder;
  
      beforeEach(function () {
          var fixture = setFixtures('<div id="demo-container" style="width: 800px;height: 600px">').find('#demo-container').get(0);
  
          placeholder = $('<div id="placeholder" style="width: 100%;height: 100%">');
          placeholder.appendTo(fixture);
          jasmine.clock().install();
      });
  
      afterEach(function () {
          if (plot) {
              plot.shutdown();
          }
          $('#placeholder').empty();
          jasmine.clock().uninstall();
      });
  
      it('should be possible to specify a cursor when creating the plot', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue'
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          expect(plot.getCursors().length).toBe(1);
          expect(firstCursor.name).toBe('Blue cursor');
      });
  
      it('should be possible to specify zero cursors when creating the plot', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: []
          });
  
          expect(plot.getCursors().length).toBe(0);
      });
  
      it('should be possible to specify multiple cursors when creating the plot', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue'
                  },
                  {
                      name: 'Red cursor',
                      color: 'red'
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          var secondCursor = plot.getCursors()[1];
          expect(plot.getCursors().length).toBe(2);
          expect(firstCursor.name).toBe('Blue cursor');
          expect(secondCursor.name).toBe('Red cursor');
      });
  
      it('should have xy mode by default', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue'
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          expect(firstCursor.mode).toBe('xy');
      });
  
      it('should be visble by default', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue'
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          expect(firstCursor.show).toBe(true);
      });
  
      it('should have a lineWidth of 1 by default', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue'
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          expect(firstCursor.lineWidth).toBe(1);
      });
  
      it('should be possible to create a cursor at runtime', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: []
          });
  
          expect(plot.getCursors().length).toBe(0);
  
          plot.addCursor({
              name: 'Blue cursor',
              mode: 'xy',
              color: 'blue',
              position: {
                  relativeX: 7,
                  relativeY: 7
              }
          });
  
          var firstCursor = plot.getCursors()[0];
  
          expect(plot.getCursors().length).toBe(1);
          expect(firstCursor.name).toBe('Blue cursor');
      });
  
      it('should be possible to remove a cursor at runtime', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue',
                      x: 3,
                      y: 1.5
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          expect(plot.getCursors().length).toBe(1);
  
          plot.removeCursor(firstCursor);
  
          expect(plot.getCursors().length).toBe(0);
      });
  
      it('should be possible to change a cursor name at runtime', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue'
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          expect(plot.getCursors().length).toBe(1);
          expect(firstCursor.name).toBe('Blue cursor');
  
          plot.setCursor(firstCursor, {
              name: 'Red Cursor'
          });
  
          expect(plot.getCursors().length).toBe(1);
          expect(firstCursor.name).toBe('Red Cursor');
      });
  
      it('should be possible to change a cursor label visibility at runtime', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue'
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          expect(plot.getCursors().length).toBe(1);
          expect(firstCursor.showLabel).toBe(false);
  
          plot.setCursor(firstCursor, {
              showLabel: true
          });
  
          expect(plot.getCursors().length).toBe(1);
          expect(firstCursor.showLabel).toBe(true);
      });
  
      it('should be possible to change a cursor mode at runtime', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue'
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          expect(plot.getCursors().length).toBe(1);
          expect(firstCursor.mode).toBe('xy');
  
          plot.setCursor(firstCursor, {
              mode: 'x'
          });
  
          expect(plot.getCursors().length).toBe(1);
          expect(firstCursor.mode).toBe('x');
      });
  
      var symbols = ['cross', 'triangle', 'square', 'diamond'];
      symbols.forEach(function (symbol, i, arr) {
          it('should be possible to make the cursor shape a ' + symbol, function () {
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [
                      {
                          name: 'Blue cursor',
                          color: 'blue',
                          symbol: symbol
                      }
                  ]
              });
  
              arr.forEach(function (symbol) {
                  spyOn(plot.drawSymbol, symbol);
              });
  
              jasmine.clock().tick(20);
  
              arr.forEach(function (s) {
                  if (s === symbol) {
                      expect(plot.drawSymbol[s]).toHaveBeenCalled();
                  } else {
                      expect(plot.drawSymbol[s]).not.toHaveBeenCalled();
                  }
              });
          });
      });
  
      it('should be possible to make the cursor shape "none"', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue',
                      symbol: 'none'
                  }
              ]
          });
  
          symbols.forEach(function (symbol) {
              spyOn(plot.drawSymbol, symbol);
          });
  
          jasmine.clock().tick(20);
  
          symbols.forEach(function (s) {
              expect(plot.drawSymbol[s]).not.toHaveBeenCalled();
          });
      });
  
      it('should be possible to change the cursor shape at runtime', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue',
                      symbol: 'diamond'
                  }
              ]
          });
  
          ['square', 'diamond'].forEach(function (symbol) {
              spyOn(plot.drawSymbol, symbol);
          });
  
          jasmine.clock().tick(20);
  
          var firstCursor = plot.getCursors()[0];
  
          plot.setCursor(firstCursor, {
              symbol: 'square'
          });
  
          jasmine.clock().tick(20);
  
          expect(plot.drawSymbol.square).toHaveBeenCalled();
      });
  
      it('should be possible to change the cursor color at runtime', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue'
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          var initialColor = firstCursor.color;
          plot.setCursor(firstCursor, {
              color: 'red'
          });
  
          expect(initialColor).toBe('blue');
          expect(firstCursor.color).toBe('red');
      });
  
      it('should be possible to change the cursor lineWidth at runtime', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue',
                      lineWidth: 2
                  }
              ]
          });
  
          var firstCursor = plot.getCursors()[0];
          var initialLineWidth = firstCursor.lineWidth;
  
          plot.setCursor(firstCursor, {
              lineWidth: 3
          });
  
          expect(initialLineWidth).toBe(2);
          expect(firstCursor.lineWidth).toBe(3);
      });
  
      it('should be possible to change the cursor visibility at runtime', function () {
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [{
                  name: 'Blue cursor',
                  color: 'blue',
                  show: true
              }]
          });
  
          var firstCursor = plot.getCursors()[0];
          var initialVisibility = firstCursor.show;
  
          plot.setCursor(firstCursor, {
              show: false
          });
  
          expect(initialVisibility).toBe(true);
          expect(firstCursor.show).toBe(false);
      });
  
      // we expect more lines to be drawn when we have more dashes
      it('should be possible to make a dashed line', function() {
          function spyOnLineTo() {
              var overlay = $('.flot-overlay')[0];
              var octx = overlay.getContext("2d");
              return spyOn(octx, 'lineTo').and.callThrough();
          }
  
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue',
                      dashes: 1
                  }
              ]
          });
  
          var spy = spyOnLineTo();
          jasmine.clock().tick(20);
  
          var oneDashCallCount = spy.calls.count();
          spy.calls.reset();
  
          plot = $.plot("#placeholder", [sampledata], {
              cursors: [
                  {
                      name: 'Blue cursor',
                      color: 'blue',
                      dashes: 5
                  }
              ]
          });
  
          jasmine.clock().tick(20);
  
          var fiveDashCallCount = spy.calls.count();
          expect(oneDashCallCount + (5 - 1) * 2).toEqual(fiveDashCallCount);
      });
  
      describe('Labels', function () {
          function spyOnFillText() {
              var overlay = $('.flot-overlay')[0];
              var octx = overlay.getContext("2d");
              return spyOn(octx, 'fillText').and.callThrough();
          }
  
          it('should display the cursor label when told so', function () {
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [
                      {
                          name: 'Blue cursor',
                          color: 'blue',
                          position: {
                              x: 1,
                              y: 1.15
                          },
                          showLabel: true
                      } ]
              });
  
              var spy = spyOnFillText();
              jasmine.clock().tick(20);
  
              expect(spy).toHaveBeenCalledWith('Blue cursor', jasmine.any(Number), jasmine.any(Number));
          });
  
          it('should not display the cursor label when told not to', function () {
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [
                      {
                          name: 'Blue cursor',
                          color: 'blue',
                          position: {
                              x: 1,
                              y: 1.15
                          },
                          showLabel: false
                      } ]
              });
  
              var spy = spyOnFillText();
              jasmine.clock().tick(20);
  
              expect(spy).not.toHaveBeenCalledWith('Blue cursor', jasmine.any(Number), jasmine.any(Number));
          });
  
          it('should display the cursor values relative to a plot when told so', function () {
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [
                      {
                          name: 'Blue cursor',
                          color: 'blue',
                          position: {
                              x: 1.0,
                              y: 1.15
                          },
                          snapToPlot: 0
                      }
                  ]
              });
  
              var spy = spyOnFillText();
              jasmine.clock().tick(20);
  
              expect(spy).toHaveBeenCalledWith('1.000, 1.1000', jasmine.any(Number), jasmine.any(Number));
          });
  
          it('should not display the cursor values relative to a plot when told not to', function () {
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [
                      {
                          name: 'Blue cursor',
                          color: 'blue',
                          position: {
                              x: 1,
                              y: 1.15
                          }
                      }
                  ]
              });
  
              var spy = spyOnFillText();
              jasmine.clock().tick(20);
  
              expect(spy).toHaveBeenCalled();
          });
  
          it('should display both the cursor label and values when told so', function () {
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [{
                      name: 'Blue cursor',
                      color: 'blue',
                      position: {
                          x: 1,
                          y: 1.15
                      },
                      showLabel: true,
                      showValues: true
                  }],
                  xaxes: [{
                      min: 0,
                      max: 10,
                      ticks: 10,
                      autoScale: "none"
                  }],
                  yaxes: [{
                      min: 1,
                      max: 1.2,
                      ticks: 10,
                      autoScale: "none"
                  }]
              });
  
              var spy = spyOnFillText();
              jasmine.clock().tick(20);
  
              expect(spy).toHaveBeenCalledWith('Blue cursor', jasmine.any(Number), jasmine.any(Number));
              expect(spy).toHaveBeenCalledWith('1.00, 1.1500', jasmine.any(Number), jasmine.any(Number));
          });
  
          it('should display the cursor label in the same format as axis', function () {
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [{
                      name: 'Blue cursor',
                      color: 'blue',
                      position: { relativeX: 0.5, relativeY: 0.5 },
                      showLabel: true,
                      showValues: true,
                      snapToPlot: undefined,
                      defaultxaxis: 1,
                      defaultyaxis: 2
                  }],
                  xaxes: [
                      { min: 0, max: 10, autoScale: "none", tickFormatter: function(val) { return '<' + val + '>'; } }
                  ],
                  yaxes: [
                      { min: 100, max: 110, autoScale: "none", tickFormatter: function(val) { return '(' + val + ')'; } },
                      { min: 100, max: 110, autoScale: "none", tickFormatter: function(val) { return '{' + val + '}'; } }
                  ]
              });
  
              var spy = spyOnFillText();
              jasmine.clock().tick(20);
  
              expect(spy).toHaveBeenCalledWith('<5>, {105}', jasmine.any(Number), jasmine.any(Number));
          });
  
          [['top right', 1.5, 1.2], ['top left', 0.5, 1.2], ['bottom right', 1.5, 1.0], ['top left', 0.5, 1.0]].forEach(function (pos) {
              describe('When cursor placed in the ' + pos[0] + ' of the plot', function () {
                  it('should display the cursor label above the values', function () {
                      plot = $.plot("#placeholder", [sampledata], {
                          cursors: [
                              {
                                  name: 'Blue cursor',
                                  color: 'blue',
                                  position: {
                                      x: pos[1],
                                      y: pos[2]
                                  },
                                  showLabel: true,
                                  showValues: true
                              }
                          ]
                      });
  
                      var spy = spyOnFillText();
                      jasmine.clock().tick(20);
  
                      var args = spy.calls.allArgs();
                      expect(args.length).toBe(2);
  
                      var cursorArgs = args.filter(function (args) {
                          return args[0] === 'Blue cursor';
                      })[0];
  
                      var valueArgs = args.filter(function (args) {
                          return args[0] !== 'Blue cursor';
                      })[0];
  
                      expect(cursorArgs[2]).toBeLessThan(valueArgs[2]);
                  });
              });
          });
      });
  
      describe('Names', function () {
          it('should give the cursors default names if not specified', function () {
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [
                      {
                          color: 'blue'
                      }
                  ]
              });
  
              var firstCursor = plot.getCursors()[0];
  
              expect(firstCursor.name).toEqual(jasmine.any(String));
              expect(firstCursor.name.length).toBeGreaterThan(0);
          });
  
          it('should give the cursors unique names');
          it('should give the cursors created at runtime unique names');
      });
  
      describe('Precision', function () {
          function spyOnFillText() {
              var overlay = $('.flot-overlay')[0];
              var octx = overlay.getContext("2d");
              return spyOn(octx, 'fillText').and.callThrough();
          }
  
          it('should give the cursors a higher precision in a big graph', function () {
              var fixture = setFixtures('<div id="demo-container" style="width: 1000px;height: 1000px">').find('#demo-container').get(0);
  
              placeholder = $('<div id="placeholder" style="width: 100%;height: 100%">');
              placeholder.appendTo(fixture);
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [
                      {
                          name: 'Blue cursor',
                          color: 'blue',
                          position: {
                              x: 1,
                              y: 1.15
                          },
                          showValues: true
                      }
                  ]
              });
  
              var spy = spyOnFillText();
              jasmine.clock().tick(20);
  
              expect(spy).toHaveBeenCalledWith('1.000, 1.1500', jasmine.any(Number), jasmine.any(Number));
          });
  
          it('should give the cursors a smaller precision in a litle graph', function () {
              var fixture = setFixtures('<div id="demo-container" style="width: 100px;height: 100px">').find('#demo-container').get(0);
  
              placeholder = $('<div id="placeholder" style="width: 100%;height: 100%">');
              placeholder.appendTo(fixture);
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [
                      {
                          name: 'Blue cursor',
                          color: 'blue',
                          position: {
                              x: 1,
                              y: 1.15
                          },
                          showValues: true
                      }
                  ]
              });
  
              var spy = spyOnFillText();
              jasmine.clock().tick(20);
  
              expect(spy).toHaveBeenCalledWith('1.00, 1.150', jasmine.any(Number), jasmine.any(Number));
          });
      });
  
      describe('cursorupdates', function() {
          it("should be called when a cursor is added", function() {
              plot = $.plot(placeholder, [sampledata], {});
  
              var spy = jasmine.createSpy('spy');
              placeholder.on('cursorupdates', spy);
  
              plot.addCursor({
                  name: 'Blue cursor',
                  mode: 'xy',
                  color: 'blue',
                  position: {
                      relativeX: 0.5,
                      relativeY: 0.5
                  }
              });
              jasmine.clock().tick(20);
  
              expect(spy).toHaveBeenCalled();
          });
  
          it("should be called with the cursors name", function() {
              var spy = jasmine.createSpy('spy');
              placeholder.on('cursorupdates', spy);
  
              var cursor,
                  oncursorupdates = function (event, cursordata) {
                      cursor = cursordata[0];
                  };
              placeholder.bind("cursorupdates", oncursorupdates);
  
              plot = $.plot(placeholder, [sampledata], {
                  cursors: [
                      {
                          name: 'Blue cursor',
                          color: 'blue',
                          position: { relativeX: 0.5, relativeY: 0.5 }
                      }
                  ]
              });
              jasmine.clock().tick(20);
  
              expect(spy).toHaveBeenCalled();
              expect(cursor.cursor).toEqual('Blue cursor');
          });
  
          it("should return the cursors intersection", function() {
              var spy = jasmine.createSpy('spy');
              placeholder.on('cursorupdates', spy);
              var cursorX, cursorY;
  
              placeholder.bind("cursorupdates", function (event, cursordata) {
                  cursorX = cursordata[0].x;
                  cursorY = cursordata[0].y;
              });
  
              plot = $.plot("#placeholder", [sampledata], {
                  cursors: [
                      {
                          name: 'Blue cursor',
                          color: 'blue',
                          position: { relativeX: 0.5, relativeY: 0.5 },
                          snapToPlot: -1
                      }
                  ]
              });
  
              jasmine.clock().tick(20);
  
              expect(spy).toHaveBeenCalled();
              expect(cursorX).toBeCloseTo(1, 8);
              expect(cursorY).toBeCloseTo(1.1, 8);
          });
      });
  });
  