
/**
 * Column move plugin
 */
function HandsontableManualColumnMove() {
  var instance
    , pressed
    , startCol
    , endCol
    , startX
    , startOffset;

  var ghost = document.createElement('DIV')
    , ghostStyle = ghost.style;

  ghost.className = 'ghost';
  ghostStyle.position = 'absolute';
  ghostStyle.top = '25px';
  ghostStyle.left = 0;
  ghostStyle.width = '10px';
  ghostStyle.height = '10px';
  ghostStyle.backgroundColor = '#CCC';
  ghostStyle.opacity = 0.7;

  var saveManualColumnPositions = function () {
    var instance = this;

    instance.PluginHooks.run('persistentStateSave', 'manualColumnPositions', instance.manualColumnPositions);
  };

  var loadManualColumnPositions = function () {
    var instance = this;
    var storedState = {};
    instance.PluginHooks.run('persistentStateLoad', 'manualColumnPositions', storedState);

    return storedState.value;
  };


  var bindMoveColEvents = function () {
    var instance = this;

    instance.rootElement.on('mousemove.manualColumnMove', function (e) {
      if (pressed) {
        ghostStyle.left = startOffset + e.pageX - startX + 6 + 'px';
        if (ghostStyle.display === 'none') {
          ghostStyle.display = 'block';
        }
      }
    });

    instance.rootElement.on('mouseup.manualColumnMove', function () {
      if (pressed) {
        if (startCol < endCol) {
          endCol--;
        }
        if (instance.getSettings().rowHeaders) {
          startCol--;
          endCol--;
        }
        instance.manualColumnPositions.splice(endCol, 0, instance.manualColumnPositions.splice(startCol, 1)[0]);
        $('.manualColumnMover.active').removeClass('active');
        pressed = false;
        instance.forceFullRender = true;
        instance.view.render(); //updates all
        ghostStyle.display = 'none';

        saveManualColumnPositions.call(instance);

        instance.PluginHooks.run('afterColumnMove', startCol, endCol);
      }
    });

    instance.rootElement.on('mousedown.manualColumnMove', '.manualColumnMover', function (e) {

      var mover = e.currentTarget;
      var TH = instance.view.wt.wtDom.closest(mover, 'TH');
      startCol = instance.view.wt.wtDom.index(TH) + instance.colOffset();
      endCol = startCol;
      pressed = true;
      startX = e.pageX;

      var TABLE = instance.$table[0];
      TABLE.parentNode.appendChild(ghost);
      ghostStyle.width = instance.view.wt.wtDom.outerWidth(TH) + 'px';
      ghostStyle.height = instance.view.wt.wtDom.outerHeight(TABLE) + 'px';
      startOffset = parseInt(instance.view.wt.wtDom.offset(TH).left - instance.view.wt.wtDom.offset(TABLE).left, 10);
      ghostStyle.left = startOffset + 6 + 'px';
    });

    instance.rootElement.on('mouseenter.manualColumnMove', 'td, th', function () {
      if (pressed) {
        var active = instance.view.THEAD.querySelector('.manualColumnMover.active');
        if (active) {
          instance.view.wt.wtDom.removeClass(active, 'active');
        }
        endCol = instance.view.wt.wtDom.index(this) + instance.colOffset();
        var THs = instance.view.THEAD.querySelectorAll('th');
        var mover = THs[endCol].querySelector('.manualColumnMover');
        instance.view.wt.wtDom.addClass(mover, 'active');
      }
    });

    instance.addHook('afterDestroy', unbindMoveColEvents);
  };

  var unbindMoveColEvents = function(){
    var instance = this;
    instance.rootElement.off('mouseup.manualColumnMove');
    instance.rootElement.off('mousemove.manualColumnMove');
    instance.rootElement.off('mousedown.manualColumnMove');
    instance.rootElement.off('mouseenter.manualColumnMove');
  }

  this.beforeInit = function () {
    this.manualColumnPositions = [];
  };

  this.init = function (source) {
    var instance = this;

    var manualColMoveEnabled = !!(this.getSettings().manualColumnMove);

    if (manualColMoveEnabled) {
      var initialManualColumnPositions = this.getSettings().manualColumnMove;

      var loadedManualColumnPositions = loadManualColumnPositions.call(instance);

      if (typeof loadedManualColumnPositions != 'undefined') {
        this.manualColumnPositions = loadedManualColumnPositions;
      } else if (initialManualColumnPositions instanceof Array) {
        this.manualColumnPositions = initialManualColumnPositions;
      } else {
        this.manualColumnPositions = [];
      }


      instance.forceFullRender = true;

      if (source == 'afterInit') {
        bindMoveColEvents.call(this);
        if (this.manualColumnPositions.length > 0) {
          this.forceFullRender = true;
          this.render();
        }

      }

    } else {
      unbindMoveColEvents.call(this);
      this.manualColumnPositions = [];
    }
  };

  this.modifyCol = function (col) {
    //TODO test performance: http://jsperf.com/object-wrapper-vs-primitive/2
    if (this.getSettings().manualColumnMove) {
      if (typeof this.manualColumnPositions[col] === 'undefined') {
        this.manualColumnPositions[col] = col;
      }
      return this.manualColumnPositions[col];
    }
    return col;
  };

  this.getColHeader = function (col, TH) {
    if (this.getSettings().manualColumnMove) {
      var DIV = document.createElement('DIV');
      DIV.className = 'manualColumnMover';
      TH.firstChild.appendChild(DIV);
    }
  };
}
var htManualColumnMove = new HandsontableManualColumnMove();

Handsontable.PluginHooks.add('beforeInit', htManualColumnMove.beforeInit);
Handsontable.PluginHooks.add('afterInit', function () {
  htManualColumnMove.init.call(this, 'afterInit')
});

Handsontable.PluginHooks.add('afterUpdateSettings', function () {
  htManualColumnMove.init.call(this, 'afterUpdateSettings')
});
Handsontable.PluginHooks.add('afterGetColHeader', htManualColumnMove.getColHeader);
Handsontable.PluginHooks.add('modifyCol', htManualColumnMove.modifyCol);


