(function ($) {
  var TestDelegate = function(length) {
    return {
      length: length,
      getRootItem: function () {
         return null;
      },
      numberOfChildrenOfItem: function(item) {
         return this.length;
      },
      childOfItem: function(index, item) {
         return index;
      },
      objectValueForItem: function(item) {
         return $('<span rel="popover" data-title=" '+item+' " data-content=" coin ">' + item + '</span>')
           .popover({delay: {show: 100, hide: 100}, trigger: 'hover'});
      },
      isLeafItem: function() {
         return false;
      },
    }
  };
  $.widget('eo.millercolumns', {
    options: {
       delegate: new TestDelegate(10),
    },
    _create: function () {
      this._delegate = this.options.delegate;
      this.columns = [];
      this.element
        .addClass('miller-columns');
      this._clear();
      this.element.on('click.millercolumns', '.miller-row', $.proxy(this._click, this));
      this.refresh();
      if (typeof this._delegate.init == 'function') {
        this._delegate.init(this);
      }
    },
    delegate: function (new_delegate) {
      if (new_delegate != undefined) {
        this._delegate = new_delegate;
      }
      return this._delegate;
    },
    _clear: function() {
      this._truncate(0);
      this._add_column(this._delegate.getRootItem());
    },
    _truncate: function(level) {
      if (level == 0) {
        var $filter = $('.miller-column', this.element);
      } else {
        var $filter = $('.miller-column:gt(' + (level-1) + ')', this.element);
      }
      $filter.remove();
      this.columns = this.columns.slice(0, level);
    },
    _click: function (e) {
        var $target = $(e.target);
        var $row = $target.is('.miller-row') ? $target : $target.parents('.miller-row');
        var $column = $row.parent();
        var item = $row.data('millerItem');
        var columnIndex = $('.miller-column', this.element).index($column);
        this._select(columnIndex, item);
        this._truncate(columnIndex+1);
        if (! $row.is('.miller-leaf')) {
          this._add_column(item);
          this.refresh();
        }
        this._delegate.selectItem(item);
    },
    _add_row: function (column, childItem) {
        var isLeaf = (typeof this._delegate.isLeafItem == 'function')
             && this._delegate.isLeafItem(childItem);
        var attributes = { 'class': 'miller-row' };
        var rowMap = this.columns[this.columns.length-1].rowMap;
        if (isLeaf) {
          attributes['class'] += ' miller-leaf';
        }
        var $row = rowMap[childItem] = $('<span/>', attributes) 
           .appendTo(column).data('millerItem', childItem);
        var objectValue = this._delegate.objectValueForItem(childItem, $row);
        if (typeof objectValue == 'string') {
          $row.html(objectValue);
        } else {
          $row.append(objectValue);
        }
    },
    _add_column: function (item) {
        var number = this._delegate.numberOfChildrenOfItem(item);
        if (number == 0) {
          return;
        }
        var column = $('<div/>', {
          'class': 'miller-column' });
        this.columns.push({item: item, element: column, rowMap: {}})
        for (i=0; i < number; i++) {
          var childItem = this._delegate.childOfItem(i, item);
          this._add_row(column, childItem);
        }
        column.appendTo(this.element);
    },
    refresh: function () {
      var container = this.element;
      $('.miller-column', this.element).each(function (i, e) {
        var level = $('.miller-column', container).index(e);
        var left_width = 0;
        $('.miller-column:lt(' + level + ')', container).each(function (key, value) {
          left_width += $(value).outerWidth();
        });
        $(e).css({'left': left_width});
        $(container).scrollLeft(left_width);
        var $column = $(e);
        var $selected = $('.miller-selected', $column);
        if ($selected.length != 0) {
          $column.scrollTop($selected.position().top+$column.scrollTop());
        }
      });
    },
    getPath: function () {
      return $('.miller-row.miller-selected', this.element).map(function (i, e) {
        return $(e).data('millerItem');
      });
    },
    _isLeafItem: function (item) {
      if (this._delegate && typeof this._delegate.isLeafItem == 'function') {
        return this._delegate.isLeafItem(item);
      }
      return false;
    },
    _select: function (columnIndex, item) {
        $('.miller-column', this.element).removeClass('miller-selected');
        $('.miller-row', this.columns[columnIndex].element).removeClass('miller-selected');
        this.columns[columnIndex].element.addClass('miller-selected');
        this.columns[columnIndex].rowMap[item].addClass('miller-selected');
        this.selected = item;
    },
    setPath: function (path) {
      this._clear();
      for (var i = 0; i < path.length; i++) {
        var item = path[i];
        this._select(i, item);
        this.columns[i].rowMap[item].addClass
        if (this._isLeafItem(item)) {
          break;
        }
        this._add_column(item);
      }
      this.refresh();
    },
    getSelection: function () {
       return this.selected;
    },
    setItem: function(item) {
      var path = this._delegate.getParents(item);
      this.setPath(path);
      this._delegate.selectItem(item);
    },
  });
})(jQuery)
