// © 2007, Applied Geographics, Inc.  All rights reserved.

function ZoomBarOrientation() {}

ZoomBarOrientation.Vertical = 0;
ZoomBarOrientation.Horizontal = 1;

function ZoomBar(id, levelCount, currentLevel, showPanDirection, orientation, targetMap, postBack) {
  this.id = id;
  this.element = document.getElementById(id);
  
  this.element.onlevelchange = null;
  this.element.onpan = null;

  this.levelCount = levelCount;
  this.currentLevel = currentLevel;
  this.showPanDirection = showPanDirection;
  this.orientation = orientation;
  this.targetMap = targetMap;
  
  this.isSliding = false;

  this.eventHandlers = [];
  this.postBack = postBack;
  
  this.attachEvent = function(eventName, handler) {
    this.eventHandlers.push({name: eventName, handler: handler});
  };
    
  this.attachEventInternal = function(element, eventName, handler) {
    if (element.attachEvent) {
      element.attachEvent("on" + eventName, handler);
    }
    else {
      element.addEventListener(eventName, handler, false);
    }
  };

  this.attachToMap = function() {
    var controller = this;
    var map = document.getElementById(this.targetMap);
    map.attachEvent("mapextentchange", function () { controller.mapExtentChanged(); });
    this.element.map = map;
  };
  
  this.disableSelection = function(element) {
    if (document.all) {
	    element.attachEvent("onselectstart", function () { return false; });
      element.unselectable = "on";
    }
    else {
	    element.addEventListener("mousedown", function (e) { e.preventDefault(); }, false);
    }
  };

  this.dispatchEvent = function(eventName, sourceEvent, eventData) {
    if (!sourceEvent) {
      sourceEvent = {type: eventName};
    }
    
    sourceEvent.eventData = eventData;
    
    for (var i = 0; i < this.eventHandlers.length; ++i) {
      if (this.eventHandlers[i].name == eventName) {
        this.eventHandlers[i].handler(sourceEvent);
      }
    }
    
    if (this.element["on" + eventName]) {
      this.element["on" + eventName](sourceEvent);
    }
  };
  
  this.getCurrentLevel = function() {
    return this.currentLevel;
  };

  this.getImage = function(id) {
    return document.getElementById(this.id + "_" + id);
  };

  this.levelChanged = function() {
    this.dispatchEvent("levelchange", null, this.currentLevel);

    if (!this.postBack) {
      if (this.element.map) {
        this.element.map.setZoomLevel(this.currentLevel);
      }
    }
    else {
      this.postBack();
    }
  };

  this.mapExtentChanged = function() {
    this.setCurrentLevel(this.element.map.getZoomLevel());
  };
  
  this.minus = function() {
    if (this.currentLevel > 1) {
      this.setCurrentLevel(this.currentLevel - 1);
      this.levelChanged();
    }
  };

  this.mouseDown = function(e) {
    var target = e.target ? e.target : e.srcElement;
    
    if (target.id.length > 0 && target.id != this.id + "_Plus" && target.id != this.id + "_Minus") {
      this.isSliding = true;
      this.setSlider(e);
    }
  };

  this.mouseMove = function(e, id) {
    if (this.isSliding) {
      var target = e.target ? e.target : e.srcElement;
    
      if (target.id.length > 0 && target.id != this.id + "_Plus" && target.id != this.id + "_Minus") {
        this.setSlider(e);
      }
    }
  };

  this.mouseUp = function() {
    if (this.isSliding) {
      this.isSliding = false;

      var newLevel = parseInt(Math.round(this.levelCount - (this.sliderPosition - 22) / 8));
      var changed = newLevel != this.currentLevel;
      
      if (changed) {
        this.setCurrentLevel(newLevel);
        this.levelChanged();
      }
    }
  };

  this.pan = function(e) {
    var x = (e.layerX ? e.layerX - 19 : e.offsetX - 18);
    var y = (e.layerY ? e.layerY - 19 : e.offsetY - 18);
    
    var tx = y * -0.70710678118655 + x * 0.70710678118655;
    var ty = y * -0.70710678118655 + x * -0.70710678118655;
    
    if (-13 <= tx && tx <= 13 && -13 <= ty && ty <= 13) {
      var dir = ty >= 0 ? (tx >= 0 ? PanDirection.North : PanDirection.West) : (tx >= 0 ? PanDirection.East : PanDirection.South)
      
      this.dispatchEvent("pan", e, dir);
      
      if (!this.postBack) {
        if (this.element.map) {
          switch (dir) {
            case PanDirection.North: this.element.map.pan(0, 0.6); break;
            case PanDirection.East: this.element.map.pan(0.6, 0); break;
            case PanDirection.South: this.element.map.pan(0, -0.6); break;
            case PanDirection.West: this.element.map.pan(-0.6, 0); break;
          }
        }
      }
      else {
        this.returnPanDirection(dir);
        this.postBack();
      }
    }
  };

  this.plus = function() {
    if (this.currentLevel < this.levelCount) {
      this.setCurrentLevel(this.currentLevel + 1);
      this.levelChanged();
    }
  };

  this.positionFromLevel = function(level) {
    return (this.levelCount - level) * 8 + 22;
  };

  this.returnPanDirection = function(dir) {
    document.getElementById(this.id + ".PanDirection").value = dir;
  };
  
  this.setCurrentLevel = function(level) {
    level = parseInt(Math.round(level));
    level = level < 1 ? 1 : (level > this.levelCount ? this.levelCount : level);

    document.getElementById(this.id + ".CurrentLevel").value = level;

    var slider = this.getImage("Slider");
    
    if (this.orientation == ZoomBarOrientation.Vertical) {
      slider.style.top = this.positionFromLevel(level) + "px";
    }
    else {
      slider.style.left = this.positionFromLevel(level) + "px";
    }
    
    this.currentLevel = level;
  };
  
  this.setSlider = function(e) {
    var target = e.target ? e.target : e.srcElement;
    var id = target.id.substr(this.id.length + 1);
    
    if (id == "Bar") {
      return;
    }
    
    if (id != "Slider") {
      this.sliderPosition = this.positionFromLevel(parseInt(id));
    }
    else {
      if (this.orientation == ZoomBarOrientation.Vertical) {
        this.sliderPosition += (e.layerY ? e.layerY : e.offsetY) - 5;
      }
      else {
        this.sliderPosition += (e.layerX ? e.layerX : e.offsetX) - 5;
      }
      
      var pos1 = this.positionFromLevel(1);
      var posc = this.positionFromLevel(this.levelCount);
      this.sliderPosition = this.sliderPosition > pos1 ? pos1 : this.sliderPosition < posc ? posc : this.sliderPosition;
    }
    
    var slider = this.getImage("Slider");
    
    if (this.orientation == ZoomBarOrientation.Vertical) {
      slider.style.top = this.sliderPosition + "px";
    }
    else {
      slider.style.left = this.sliderPosition + "px";
    }
  };

  this.sliderPosition = this.positionFromLevel(this.currentLevel);

  var controller = this;
  
  if (this.showPanDirection) {
    var pan = this.getImage("Pan");
    this.attachEventInternal(pan, "mousedown", function (e) { controller.pan(e); });
  }
  
  var slider = this.getImage("Slider");
  this.disableSelection(slider);
  
  if (this.orientation == ZoomBarOrientation.Vertical) {
    slider.style.top = this.sliderPosition + "px";
  }
  else {
    slider.style.left = this.sliderPosition + "px";
  }

  for (var i = 1; i <= this.levelCount; ++i) {
    var image = this.getImage(i);
    this.disableSelection(image);
  }
  
  var plus = this.getImage("Plus");
  this.attachEventInternal(plus, "click", function () { controller.plus(); });
  this.disableSelection(plus);
  
  var minus = this.getImage("Minus");
  this.attachEventInternal(minus, "click", function () { controller.minus(); });
  this.disableSelection(minus);
  
  var bar = document.getElementById(id + "_Bar");
  this.attachEventInternal(bar, "mousedown", function (e) { controller.mouseDown(e); });
  this.attachEventInternal(bar, "mousemove", function (e) { controller.mouseMove(e); });
  this.attachEventInternal(bar, "mouseup", function () { controller.mouseUp(); });
  
  this.element.controller = this;
  
  this.element.attachEvent = function(eventName, handler) { this.controller.attachEvent(eventName, handler); };
  this.element.getCurrentLevel = function() { return this.controller.getCurrentLevel(); };
  this.element.setCurrentLevel = function(level) { this.controller.setCurrentLevel(level); };

  if (targetMap != null && !this.postBack) {
    this.attachEventInternal(window, "load", function () { controller.attachToMap(); });
  }
  
  return this.element;
}
