/* Copyright (c) 2006-2007 MetaCarta, Inc., published under the BSD license.
 * See http://svn.openlayers.org/trunk/openlayers/release-license.txt
 * for the full text of the license. */


/**
 * @requires OpenLayers/Control/PanZoom.js
 *
 * Class: OpenLayers.Control.PanZoomBar
 *
 * Inherits from:
 *  - <OpenLayers.Control.PanZoom>
 *  - <OpenLayers.Control>
 */
OpenLayers.Control.PanZoomBar2 = OpenLayers.Class(OpenLayers.Control.PanZoom, {

    /**
     * APIProperty: zoomStopWidth
     */
    zoomStopWidth: 18,

    /**
     * APIProperty: zoomStopHeight
     */
    zoomStopHeight: 11,

    /**
     * Property: slider
     */
    slider: null,

    /**
     * Property: sliderEvents
     * {<OpenLayers.Events>}
     */
    sliderEvents: null,

    /**
     * Property: zoomBarDiv
     * {DOMElement}
     */
    zoomBarDiv: null,

    /**
     * Property: divEvents
     * {<OpenLayers.Events>}
     */
    divEvents: null,

    /**
     * Constructor: <OpenLayers.Control.PanZoomBar>
     */
    initialize: function() {
        OpenLayers.Control.PanZoom.prototype.initialize.apply(this, arguments);
    },

    /**
     * APIMethod: destroy
     */
    destroy: function() {

        this.div.removeChild(this.slider);
        this.slider = null;

        this.sliderEvents.destroy();
        this.sliderEvents = null;

        this.div.removeChild(this.zoombarDiv);
        this.zoomBarDiv = null;

        this.divEvents.destroy();
        this.divEvents = null;

        this.map.events.unregister("zoomend", this, this.moveZoomBar);
        this.map.events.unregister("changebaselayer", this, this.redraw)

        OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments);
    },

    /**
     * Method: setMap
     *
     * Parameters:
     * map - {<OpenLayers.Map>}
     */
    setMap: function(map) {
        OpenLayers.Control.PanZoom.prototype.setMap.apply(this, arguments);
        this.map.events.register("changebaselayer", this, this.redraw);
    },

    /**
     * Method: redraw
     * clear the div and start over.
     */
    redraw: function() {
        if (this.div != null) {
            this.div.innerHTML = "";
        }
        this.draw();
    },

    /**
    * Method: draw
    *
    * Parameters:
    * px - {<OpenLayers.Pixel>}
    */
    draw: function(px) {
        // initialize our internal div
        OpenLayers.Control.prototype.draw.apply(this, arguments);
        px = this.position.clone();
        px.x = px.x -5;

        // place the controls
        this.buttons = [];

        var sz = new OpenLayers.Size(19,19);
        //Use three column vars that get updated as we go through rows
        var left = new OpenLayers.Pixel(px.x, px.y);
        var centered = new OpenLayers.Pixel(px.x+1+sz.w, px.y);
        var right = new OpenLayers.Pixel(px.x+2+sz.w*2, px.y);

        //First Row - no adjusting
        this._addButton("panup", "../images/panzoombar_up.png", centered, sz);
        //Second row - add height of buttons + 1
        left.y = left.y + sz.h + 1; centered.y = centered.y + sz.h + 1; right.y = right.y + sz.h + 1;
        this._addButton("panleft", "../images/panzoombar_left.png", left, sz);
        this._addButton("zoomworld", "../images/panzoombar_center.png", centered, sz);
        this._addButton("panright", "../images/panzoombar_right.png", right, sz);
        //Third row - add height of buttons + 1
        left.y = left.y + sz.h + 1; centered.y = centered.y + sz.h + 1; right.y = right.y + sz.h + 1;
        this._addButton("pandown", "../images/panzoombar_down.png", centered, sz);
        //Fourth row - add height of buttons + 1
        left.y = left.y + sz.h + 1; centered.y = centered.y + sz.h + 1; right.y = right.y + sz.h + 1;
        this._addButton("zoomin", "../images/panzoombar_in.png", centered, sz);
        //Fifth row - add height of buttons + 1
        left.y = left.y + sz.h + 1; centered.y = centered.y + sz.h + 1; right.y = right.y + sz.h + 1;
        centered = this._addZoomBar(centered);
        this._addButton("zoomout", "../images/panzoombar_out.png", centered, sz);
        return this.div;
    },

    /**
    * Method: _addZoomBar
    *
    * Parameters:
    * location - {<OpenLayers.Pixel>} where zoombar drawing is to start.
    */
    _addZoomBar:function(centered) {
        var imgLocation = OpenLayers.Util.getImagesLocation();

        var id = "OpenLayers_Control_PanZoomBar_Slider" + this.map.id;
        var zoomsToEnd = this.map.getNumZoomLevels() - 1 - this.map.getZoom();
        var slider = OpenLayers.Util.createAlphaImageDiv(id,
                       centered.add(-1, zoomsToEnd * this.zoomStopHeight),
                       new OpenLayers.Size(20,9),
                       imgLocation+"../images/panzoombar_slider.png",
                       "absolute");
        this.slider = slider;

        this.sliderEvents = new OpenLayers.Events(this, slider, null, true);
        this.sliderEvents.register("mousedown", this, this.zoomBarDown);
        this.sliderEvents.register("mousemove", this, this.zoomBarDrag);
        this.sliderEvents.register("mouseup", this, this.zoomBarUp);
        this.sliderEvents.register("dblclick", this, this.doubleClick);
        this.sliderEvents.register("click", this, this.doubleClick);

        sz = new OpenLayers.Size();
        sz.h = this.zoomStopHeight * this.map.getNumZoomLevels();
        sz.w = this.zoomStopWidth;
        var div = null

        if (OpenLayers.Util.alphaHack()) {
            var id = "OpenLayers_Control_PanZoomBar" + this.map.id;
            div = OpenLayers.Util.createAlphaImageDiv(id, centered,
                                      new OpenLayers.Size(sz.w,
                                              this.zoomStopHeight),
                                      imgLocation + "../images/panzoombar.png",
                                      "absolute", null, "crop");
            div.style.height = sz.h;
        } else {
            div = OpenLayers.Util.createDiv(
                        'OpenLayers_Control_PanZoomBar_Zoombar' + this.map.id,
                        centered,
                        sz,
                        imgLocation+"../images/panzoombar.png");
        }

        this.zoombarDiv = div;

        this.divEvents = new OpenLayers.Events(this, div, null, true);
        this.divEvents.register("mousedown", this, this.divClick);
        this.divEvents.register("mousemove", this, this.passEventToSlider);
        this.divEvents.register("dblclick", this, this.doubleClick);
        this.divEvents.register("click", this, this.doubleClick);

        this.div.appendChild(div);

        this.startTop = parseInt(div.style.top);
        this.div.appendChild(slider);

        this.map.events.register("zoomend", this, this.moveZoomBar);

        centered = centered.add(0,
            this.zoomStopHeight * this.map.getNumZoomLevels());
        return centered;
    },

    /*
     * Method: passEventToSlider
     * This function is used to pass events that happen on the div, or the map,
     * through to the slider, which then does its moving thing.
     *
     * Parameters:
     * evt - {<OpenLayers.Event>}
     */
    passEventToSlider:function(evt) {
        this.sliderEvents.handleBrowserEvent(evt);
    },

    /*
     * Method: divClick
     * Picks up on clicks directly on the zoombar div
     *           and sets the zoom level appropriately.
     */
    divClick: function (evt) {
        if (!OpenLayers.Event.isLeftClick(evt)) return;
        var y = evt.xy.y;
        var top = OpenLayers.Util.pagePosition(evt.object)[1];
        var levels = Math.floor((y - top)/this.zoomStopHeight);
        this.map.zoomTo((this.map.getNumZoomLevels() -1) -  levels);
        OpenLayers.Event.stop(evt);
    },

    /*
     * Method: zoomBarDown
     * event listener for clicks on the slider
     *
     * Parameters:
     * evt - {<OpenLayers.Event>}
     */
    zoomBarDown:function(evt) {
        if (!OpenLayers.Event.isLeftClick(evt)) return;
        this.map.events.register("mousemove", this, this.passEventToSlider);
        this.map.events.register("mouseup", this, this.passEventToSlider);
        this.mouseDragStart = evt.xy.clone();
        this.zoomStart = evt.xy.clone();
        this.div.style.cursor = "move";
        // reset the div offsets just in case the div moved
        this.zoombarDiv.offsets = null;
        OpenLayers.Event.stop(evt);
    },

    /*
     * Method: zoomBarDrag
     * This is what happens when a click has occurred, and the client is
     * dragging.  Here we must ensure that the slider doesn't go beyond the
     * bottom/top of the zoombar div, as well as moving the slider to its new
     * visual location
     *
     * Parameters:
     * evt - {<OpenLayers.Event>}
     */
    zoomBarDrag:function(evt) {
        if (this.mouseDragStart != null) {
            var deltaY = this.mouseDragStart.y - evt.xy.y
            var offsets = OpenLayers.Util.pagePosition(this.zoombarDiv);
            if ((evt.clientY - offsets[1]) > 0 &&
                (evt.clientY - offsets[1]) < parseInt(this.zoombarDiv.style.height) - 2) {
                var newTop = parseInt(this.slider.style.top) - deltaY;
                this.slider.style.top = newTop+"px";
            }
            this.mouseDragStart = evt.xy.clone();
            OpenLayers.Event.stop(evt);
        }
    },

    /*
     * Method: zoomBarUp
     * Perform cleanup when a mouseup event is received -- discover new zoom
     * level and switch to it.
     *
     * Parameters:
     * evt - {<OpenLayers.Event>}
     */
    zoomBarUp:function(evt) {
        if (!OpenLayers.Event.isLeftClick(evt)) return;
        if (this.zoomStart) {
            this.div.style.cursor="";
            this.map.events.unregister("mouseup", this, this.passEventToSlider);
            this.map.events.unregister("mousemove", this, this.passEventToSlider);
            var deltaY = this.zoomStart.y - evt.xy.y
            this.map.zoomTo(this.map.zoom + Math.round(deltaY/this.zoomStopHeight));
            this.moveZoomBar();
            this.mouseDragStart = null;
            OpenLayers.Event.stop(evt);
        }
    },

    /*
    * Method: moveZoomBar
    * Change the location of the slider to match the current zoom level.
    */
    moveZoomBar:function() {
        var newTop =
            ((this.map.getNumZoomLevels()-1) - this.map.getZoom()) *
            this.zoomStopHeight + this.startTop + 1;
        this.slider.style.top = newTop + "px";
    },

    CLASS_NAME: "OpenLayers.Control.PanZoomBar"
});
