/***

MochiKit.Maps__Schmap 0.2

(c) 2007 Schmap ltd.  All rights Reserved.

***/
var isIE6 = b_version.search(/MSIE 6/i) != -1;

if (typeof(dojo) != 'undefined') {
    dojo.provide('MochiKit.Maps__Schmap');
}

if (typeof(MochiKit) == 'undefined') {
    MochiKit = {};
}

if (typeof(MochiKit.Maps__Schmap) == 'undefined') {
    MochiKit.Maps__Schmap = {};
}

if (typeof(MochiKit.Maps) == 'undefined') {
    // provide default implementation
    MochiKit.Maps = MochiKit.Maps__Schmap;
}

MochiKit.Maps__Schmap.NAME = "MochiKit.Maps__Schmap";
MochiKit.Maps__Schmap.VERSION = "0.2";
MochiKit.Maps__Schmap.__repr__ = function () {
    return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.Maps__Schmap.toString = function () {
    return this.__repr__();
};

MochiKit.Maps__Schmap.OutOfBounds = function() {
    this.message = 'Out of bounds!';
    this.name = 'OutOfBounds';
}

MochiKit.Maps__Schmap.OutOfBounds.prototype.toString = function() {
    return(this.message);
}

MochiKit.Maps__Schmap.scaleImage = function(ds, sizes) {
    var imgData = ds[0];
    var images = [];
    for(var i = 0; i < sizes.length; i++) {
        var thisImg = clone(imgData);
        thisImg.w = Math.round(imgData.w * sizes[i]);
        thisImg.h = Math.round(imgData.h * sizes[i]);
        images.push(thisImg);
    }
    return images;
};

MochiKit.Maps__Schmap.Map = function(element, options) {
    this.parentElement = $(element);
    this.element = DIV({id: 'MochiKit.Maps__Schmap.Map.' +
                            MochiKit.Maps__Schmap.Map._id_pool + '.container',
                        style: 'position: absolute; height: 100%; width:100%; top: 0px; bottom: 0px; right: 0px; left: 0px;' +
                               'overflow: hidden; margin: 0px; padding: 0px; ' +
                               'background: white;'});
    this.imgElement = IMG({id: 'MochiKit.Maps__Schmap.Map.' +
                               MochiKit.Maps__Schmap.Map._id_pool + '.img',
                           style: 'z-index: 1; position: absolute; ' +
                                  'top: 0px; left: 0px;'});
    this.markersElement = DIV({id: 'MochiKit.Maps__Schmap.Map.' +
                                   (MochiKit.Maps__Schmap.Map._id_pool++) +
                                   '.markers',
                               style: 'z-index: 2; height: 100%; ' +
                                      'margin: 0px; padding: 0px;' +
                                      'position: relative'});
    this.parentElement.appendChild(this.element);
    appendChildNodes(this.element, this.markersElement, this.imgElement);
    this.provider = 's';
    this.bounds = this.imgBounds = null;
    this.images = [];
    this._items = [];
    //connect(window, 'onresize', bind(this.fixSize, this));  NPF
    if(options && options.enableDrag) {
        connect(this.markersElement, 'onmousedown', this, '_panDrag');
        connect(this.imgElement, 'onmousedown', this, '_panDrag');
    }
    if(options && (options.ds !== undefined)) {
        this.ds = options.ds;
    } else {
        this.ds = MochiKit.Maps__Schmap.Map.ds;
    }
    this.render = "";
    this.logo = [];
    if(schmapplet.permanentLogo) {
	   for(var i=0;i <mapLogo.length;i++) {
	    var logo = this.setLogo(mapLogo[i],0);
        this.logo.push(logo);
	   }
    } else {
      if (typeof(xparams) != 'undefined' ) {
          var logo1 = this.setLogo(xparams, 0);
      } 
	  var logo2 = this.setLogo(schmapplet, 1);
	  if (logo1 != null) {
            this.logo.push(logo1);
      }
      if (typeof(logo2) != 'undefined' && logo2 != null) {
         this.logo.push(logo2);
      }
    }
	if(typeof(xparams) != 'undefined'
            && typeof(xparams.simpleMapLogo) != 'undefined') {
	    var tem ={};
	    tem.simpleMapLogo = xparams.simpleMapLogo;
	    tem.align = 'rightBottom';
	    var logo = this.setLogo(tem, 0);	
            if (logo != null) {
                this.logo.push(logo);
            }
	}
    this.hideAll(true);
    this.feed();
};

MochiKit.Maps__Schmap.Map.prototype.loadNewData = function (path) {
    logDebug('start loadNewData');
    var idents = keys(MochiKit.Maps__Schmap.Map.datafiles);

    // if(this.render === path) {
	//	console.log("same data as the current one:", window[this.ds]);
        // MochiKit.Maps__Schmap.Map.newDataArrived = false;
        // return false;
    // }
    logDebug("starting to load script...");
    MochiKit.Maps__Schmap.Map.newDataArrived = true;
    return true;
}

MochiKit.Maps__Schmap.Map.prototype.feed = function () {
    logDebug("feed");
    var ds = window[this.ds];
    //console.log("feed new data:", ds);
    if(!ds) {
        logError("the map data is not loaded (successfully)");
        return;
    }
    this.render = ds[0];
    var newDataArrived = MochiKit.Maps__Schmap.Map.newDataArrived;
    if(newDataArrived) {
        MochiKit.Maps__Schmap.Map.datafiles[this.render] = ds;
    }

    var scale = ds[1];
    if(scale && scale['sizeFactors'] !== undefined && newDataArrived) {
        //scale = ds.shift();
        var sizeFactors = scale['sizeFactors'];
        var imageData = ds[2];
        if(imageData && imageData.length) {
            ds[2] = MochiKit.Maps__Schmap.scaleImage(ds[2], sizeFactors);
        }
        else {
            logDebug("the map image info is not provided.");
        }
    } else {
        logDebug("the map image sizeFactors is not provided");
    }
    
    var latitudes = ds[4];
    this.pixelLatitudes = [];
    if (latitudes && latitudes['pixelLatitudes'] !== undefined) {
        this.pixelLatitudes = latitudes['pixelLatitudes'];
        //alert ('pixelLatitudes[0]=' + this.pixelLatitudes[0] + '; pixelLatitudes[1]=' + this.pixelLatitudes[1]);
    }

    //this.setImages.apply(this, ds.slice(2, 4));
	this.setImages(ds[2], ds[3]);
}

MochiKit.Maps__Schmap.Map.prototype.__repr__ = function () {
    return "[Map at " + this.element.id + "]";
};

MochiKit.Maps__Schmap.Map._id_pool = 0;
MochiKit.Maps__Schmap.Map.ds = "schmapdata";
MochiKit.Maps__Schmap.Map.datafiles = {};
MochiKit.Maps__Schmap.Map.newDataArrived = true;

MochiKit.Maps__Schmap.Map.prototype.setBackground = function(style) {
    setStyle(this.element, {background: style});
};

MochiKit.Maps__Schmap.Map.prototype.setImages = function(list, bounds) {
    this.images = [];
    this.imgBounds = clone(bounds);
    var preloader = new Image();
    for(var i = 0; i < list.length; i++) {
        var img = clone(list[i]);
        preloader.src = img.src;
        img.zoomFactors = {x: img.w / (bounds.east - bounds.west),
                           y: img.h / (bounds.north - bounds.south)};
        this.images.push(img);
    }
    this.images.sort(function(a, b) {return compare(a.w, b.w);});
	this.markersElementPosition = getElementPosition(this.markersElement);
    signal(this, 'load');
    //this.zoomToBounds(bounds);

};
MochiKit.Maps__Schmap.Map.prototype.setLogo = function(pathObj, force) {
    if(typeof(pathObj["mapLogo"]) != 'undefined'
        && pathObj["mapLogo"]!= '') {
		    var path = pathObj["mapLogo"];
		} else if(typeof(pathObj["simpleMapLogo"]) != 'undefined'
         && pathObj["simpleMapLogo"]!= ''){
		   var path = pathObj["simpleMapLogo"];
    } else {
	   return null;
	}
    //var path = pathObj["mapLogo"];
    pathparam = path.substr(path.length-18);
    var logo = {};
    logo.name = path;
    logo.width = Number(pathparam.substr(0,3));
    logo.height = Number(pathparam.substr(3,3));
    logo.xoff = pathparam.substr(6,3);
    logo.yoff = pathparam.substr(9,3);
    logo.hasURL = Number(pathparam.substr(12,1));
    logo.strong = Number(pathparam.substr(13,1));
    var mapSize = getElementDimensions(this.parentElement);
	logo.xoffset = (mapSize.w-logo.width)*Number(logo.xoff)/100;
	logDebug(mapSize.h,logo.height,logo.yoff);
	logo.yoffset = (mapSize.h-logo.height)*(100-Number(logo.yoff))/100;
    logo.img =  PNG({width: logo.width, height: logo.height,
                    src: "/images/minitemplate/schmapmaps/"+logo.name, style:"z-index:50; position:absolute; left:"+
                    logo.xoffset+"px; bottom:"+logo.yoffset+"px" });

    if(logo.hasURL){
        if(typeof(pathObj["logoLink"]) != 'undefined'
            && pathObj["logoLink"] != null){
            setStyle(logo.img, {'cursor':'pointer'});
            connect(logo.img,'onclick',function(){
                                        window.open(pathObj["logoLink"]);
                                    });
        }
    }
    if(logo.strong || schmapplet.schmapMapLogo == undefined || force){
        this.parentElement.appendChild(logo.img);
        return logo;
    }
    return null;
};

MochiKit.Maps__Schmap.Map.prototype.repositionLogos = function() {
    if (this.logo != null)
    {
        for (var i=0; i < this.logo.length; i++)
        {
            var thisLogo = this.logo[i];
	    var mapSize = getElementDimensions(this.parentElement);
	    thisLogo.xoffset = (mapSize.w-thisLogo.width)*(Number(thisLogo.xoff)/100);
	    thisLogo.yoffset = (mapSize.h-thisLogo.height)*(100-Number(thisLogo.yoff))/100;
		if(typeof(thisLogo.align) !='undefined' 
	         && thisLogo.align == 'rightBottom'){
			setStyle(thisLogo.img,{'right':thisLogo.xoffset+"px"}); 
		} else {
		    setStyle(thisLogo.img,{'left':thisLogo.xoffset+"px"});
		}
            setStyle(thisLogo.img,{'bottom':thisLogo.yoffset+"px"});
        }
    }
}

MochiKit.Maps__Schmap.Map.prototype.fixSize = function(noupdate) {
    var d = getElementDimensions(this.element);
    this.screenCenter = new MochiKit.Style.Coordinates(d.w / 2, d.h / 2);
    this.screenGeoRadius = {w: this.screenCenter.x / this.zoomFactors.x,
                            h: this.screenCenter.y / this.zoomFactors.y};
    if(!noupdate) {
        signal(this, 'moveend');
        this.__display__();
    }
};

MochiKit.Maps__Schmap.Map.prototype.getBoundsFromCenter = function(point) {
    var latitude = point.latitude;
    var centerYPos = this.getYPosFromLat (latitude);
    var mapViewSize = getElementDimensions(this.parentElement);
    scaledMapViewHeight = mapViewSize.h / this.heightRatio;
    var mapViewHalfHeight = scaledMapViewHeight / 2;
    var topYPos = centerYPos - mapViewHalfHeight;
    
    var bottomYPos = centerYPos + mapViewHalfHeight;
    
    if (topYPos < 0)
    {
        topYPos = 0;
        bottomYPos += (-topYPos);
    }
    
    if (bottomYPos > xparams.imgSize.h)
    {
        topYPos -= (bottomYPos - xparams.imgSize.h)
        bottomYPos = xparams.imgSize.h;
    }
    
    var latOfTop = this.getLatFromYPos (topYPos);
    var latOfBottom = this.getLatFromYPos (bottomYPos);
    
    return (new MochiKit.Maps__Schmap.Bounds (latOfTop,
                                              point.longitude - this.screenGeoRadius.w,
                                              latOfBottom,
                                              point.longitude + this.screenGeoRadius.w));
};
MochiKit.Maps__Schmap.Map.prototype._setCenter = function(point) {
//alert ('Entered _setCenter');
    if(point === undefined) {
        if(this.bounds === null) return;
        point = this.bounds.getCenter();
    } else if(point instanceof MochiKit.Style.Coordinates) {
        point = {y: point.y - this.screenCenter.y,
                 x: point.x - this.screenCenter.x};
        point = new MochiKit.Maps__Schmap.Point(this.imgBounds.north +
                                                point.y / this.zoomFactors.y,
                                                this.imgBounds.west -
                                                point.x / this.zoomFactors.x);
        logDebug('moving from', repr(this.bounds.getCenter()), 'to', repr(point));
    } else
        point = clone(point);

    this.bounds = this.getBoundsFromCenter (point);
    this.setDisplayFromBounds (this.bounds);

    return point;
};

MochiKit.Maps__Schmap.Map.prototype.getNewMapXYPos = function(bounds) {
    var yPixelPosNorth = this.getYPosFromLat (bounds.north);
    yPixelPosNorth = yPixelPosNorth * this.heightRatio;
    var yPixelPosSouth = this.getYPosFromLat (bounds.south);
    yPixelPosSouth = yPixelPosSouth * this.heightRatio;
    var x1 = Math.round((bounds.west - this.imgBounds.west) * this.zoomFactors.x);
    var x2 = Math.round((bounds.east - this.imgBounds.west) * this.zoomFactors.x);
    var widthIdealMap = x2 - x1;
    var heightIdealMap = yPixelPosSouth - yPixelPosNorth;

    var mapViewArea = getElementDimensions (this.parentElement);
    
    var newMapXLeftPos = x1 - ((mapViewArea.w - widthIdealMap) / 2);
    if (newMapXLeftPos < 0)
    {
        newMapXLeftPos = 0;
    }
    if (newMapXLeftPos + mapViewArea.w > this.imgElement.width)
    {
        newMapXLeftPos = this.imgElement.width - mapViewArea.w;
    }
    var newMapYTopPos = yPixelPosNorth - ((mapViewArea.h - heightIdealMap) / 2);
    if (newMapYTopPos < 0)
    {
        newMapYTopPos = 0;
    }
    if (newMapYTopPos + mapViewArea.h > this.imgElement.height)
    {
        newMapYTopPos = this.imgElement.height - mapViewArea.h;
    }
    return (new MochiKit.Style.Coordinates(newMapXLeftPos, newMapYTopPos));
}

MochiKit.Maps__Schmap.Map.prototype.setDisplayFromBounds = function(bounds) {
        
    var newPos = this.getNewMapXYPos (bounds);
    if (newPos != null)
    {
        setElementPosition(this.imgElement, {x: -(newPos.x), y: -(newPos.y)});
                                             
        // We need to adjust the bounds now to reflect the actual display
        var mapViewArea = getElementDimensions (this.parentElement);
        var bounds = clone(bounds);
        bounds.west = this.imgBounds.west + (newPos.x / this.zoomFactors.x);
        
        var newMapRightPos = newPos.x + mapViewArea.w;
        bounds.east = this.imgBounds.west + (newMapRightPos / this.zoomFactors.x)
        
        bounds.north = this.getLatFromYPos (newPos.y);
        //alert ('this.heightRatio=' + this.heightRatio);
        bounds.south = this.getLatFromYPos ((newPos.y + mapViewArea.h)/this.heightRatio);
    
        this.__display__();
        this.bounds = bounds;
        //alert ('New bounds=(' + this.bounds.north + ',' + this.bounds.west + ',' + this.bounds.south + ',' + this.bounds.east + ')');
    }
}

MochiKit.Maps__Schmap.Map.prototype.actualBoundsFromIdealBounds = function (bounds)
{
    var adjustedBounds = clone(bounds);
    var newPos = this.getNewMapXYPos (bounds);
    if (newPos != null)
    {            
        var mapViewArea = getElementDimensions (this.parentElement);
        
        // Make the 'actual' bounds a little smaller than they really are so that the map auto-pan when an icon
        // is very close to the edge of the map
        var adjX = newPos.x;
        adjustedBounds.west = this.imgBounds.west + (adjX / this.zoomFactors.x);
        
        var newMapRightPos = newPos.x + mapViewArea.w;
        adjustedBounds.east = this.imgBounds.west + (newMapRightPos / this.zoomFactors.x);
          
        var adjY = newPos.y;
        adjY = adjY / this.heightRatio;
        adjustedBounds.north = this.getLatFromYPos (adjY);
        var newY = (newPos.y + mapViewArea.h) / this.heightRatio;
        adjustedBounds.south = this.getLatFromYPos (newY, true);
    }
    return (adjustedBounds);
}

MochiKit.Maps__Schmap.Map.prototype.setDisplay = function(point, zoom) {
    if(!this.imgBounds.contains(point))
        throw new MochiKit.Maps__Schmap.OutOfBounds();
    if(this.bounds === null) {
        var oldCenter = null;
        var oldZoom = null;
    } else {
        var oldCenter = this.bounds.getCenter();
        var oldZoom = this.currentZoom;
    }
    /** NPF
    if(zoom !== undefined) {
        if(zoom > 1) {
            logWarning('please correct your setDisplay calls to use a number from 0 to 1');
            zoom /= 18;
        }
        this.bounds = null; // avoid _setCenter()
        this.zoomTo(zoom, true);
    }
    **/
    point = this._setCenter(point);
    this.__display__();
    if((oldZoom === null) || (oldZoom != this.currentZoom))
        signal(this, 'zoomend');
    if((oldCenter === null) ||
       (point.latitude != oldCenter.latitude) ||
       (point.longitude != oldCenter.longitude))
        signal(this, 'moveend');
};

MochiKit.Maps__Schmap.Map.prototype._zoomTo = function(i) {
    //if(this.currentZoom == i)
    //{
    //    return;
    //}
    this.currentZoom = i;
    var img = this.images[this.currentZoom];
    this.imgElement.width = img.w + 1;
    this.imgElement.height = img.h;
    this.imgElement.src = img.src;
	mapobj = this; 
	if(schmapplet.readyToMakeIcons){
		this.imgElement.onload = function(){ //alert(33);
			mapobj.hideAll(false);
			schmapplet.readyToMakeIcons = false;
		};
		if(this.imgElement.complete){
		this.hideAll(false);
		schmapplet.readyToMakeIcons = false;
		}
    }else{
	this.imgElement.onload = null;
		}
	this.zoomFactors = img.zoomFactors;
    this.fixSize(true);
    this._setCenter();
    if(this.bounds !== null)
        signal(this, 'zoomend');
};

MochiKit.Maps__Schmap.Map.prototype.zoomIn = function() {
    if(this.currentZoom + 1 < this.images.length)
    {
        this._zoomTo(this.currentZoom + 1);
    }
    this.__display__();
};

MochiKit.Maps__Schmap.Map.prototype.zoomOut = function() {
    if(this.currentZoom)
        this._zoomTo(this.currentZoom - 1);
    this.__display__();
};

MochiKit.Maps__Schmap.Map.prototype.zoomTo = function(level, noupdate) {
    this._zoomTo(Math.round(level * (this.images.length - 1)));
    if(!noupdate) {
        this.__display__();
    }
};

MochiKit.Maps__Schmap.Map.prototype.getZoom = function() {
    return this.currentZoom && (this.currentZoom / (this.images.length - 1));
};

MochiKit.Maps__Schmap.Map.prototype.zoomToBounds = function(bounds) {
        
    //if(this.bounds &&
    //   (this.bounds.equals(bounds) || !this.bounds.contains(bounds))) {
    //    this._zoomTo(0);
    //} else {
        var d = getElementDimensions(this.element);
        var i = 0;
        do {
            var needed = this.convert(bounds, this.images[i]);
            if((needed[1].w > d.w) && (needed[1].h > d.h))
            {
                break;
            }
            i++;
        } while(i < this.images.length);
		if(i==this.images.length) i--;
        if(typeof(xparams) != 'undefined'
            && typeof(xparams.imgSize) != 'undefined'
            && xparams.imgSize )
          this.heightRatio = this.images[i].h / xparams.imgSize.h;   // NPF - mercator
      else
          this.heightRatio = 1;
        this._zoomTo(i);
    //}
    this.setDisplayFromBounds(bounds);
    this.__display__();
};

MochiKit.Maps__Schmap.Map.prototype.getLatFromYPos = function(ypos) {    
    var foundLat = this.pixelLatitudes[1];
    var foundSeg = false;
    var currSegNum = 0;
    var currPx = this.pixelLatitudes[currSegNum];
    var nextPx = this.pixelLatitudes[currSegNum+2];
    while (!foundSeg)
    {
        
        if (ypos <= nextPx && ypos >= currPx)
        {
            foundSeg = true;
            var latTop = this.pixelLatitudes[currSegNum + 1];
            var latBottom = this.pixelLatitudes[currSegNum + 3];
            var pctPos = (ypos - currPx) / (nextPx - currPx);
            
            foundLat = latTop - ((latTop - latBottom) * pctPos);                
        }
        else if (currSegNum + 4 >= this.pixelLatitudes.length)
        {
            //alert ('Latitude not found!!');
            foundSeg = true;
            foundLat = this.pixelLatitudes[currSegNum + 3];
        }
        else
        {
            currSegNum += 2;
            currPx = this.pixelLatitudes[currSegNum];
            nextPx = this.pixelLatitudes[currSegNum+2];
        } 
        
    }
    return (foundLat);
};

MochiKit.Maps__Schmap.Map.prototype.getYPosFromLat = function(latitude, log) {
    var pxTop;
    var pxBottom;
    var yPos = 0;
    var foundSeg = false;
    var currSegNum = 1;
    var currSegNorth = this.pixelLatitudes[currSegNum];
    var currSegSouth = this.pixelLatitudes[currSegNum+2];
    //alert ('i.zoomFactors.y=' + i.zoomFactors.y);
    while (!foundSeg)
    {
        if (latitude <= currSegNorth && latitude >= currSegSouth)
        {
            
            foundSeg = true;
            pxTop = this.pixelLatitudes[currSegNum - 1];
            pxBottom = this.pixelLatitudes[currSegNum + 1];
            //alert ('pxTop=' + pxTop + '; pxBottom=' + pxBottom);
            var pctPos = (currSegNorth - latitude) / (currSegSouth - currSegNorth);
            yPos = pxTop + Math.round((pxTop - pxBottom) * pctPos);
                            
            //c.y += (pxTop + Math.round((pxTop - pxBottom) * pctPos));
            //alert ('c.y=' + c.y);
                
        }
        
        if (!foundSeg)
        {
            if (currSegNum + 4 >= this.pixelLatitudes.length)
            {
                //alert ('Latitude not found!! - latitude=' + latitude);
                foundSeg = true;
                yPos = pxBottom;
            }
            else
            {
                currSegNum += 2;
                currSegNorth = this.pixelLatitudes[currSegNum];
                currSegSouth = this.pixelLatitudes[currSegNum+2];
                pxTop = this.pixelLatitudes[currSegNum - 1];
                pxBottom = this.pixelLatitudes[currSegNum + 1];
            } 
        }
    }
    return (yPos);
};

MochiKit.Maps__Schmap.Map.prototype.getBounds = function() {
    return clone(this.bounds);
};

MochiKit.Maps__Schmap.Map.prototype.setMapType = function(maptype) {
};

MochiKit.Maps__Schmap.Map.prototype.convert = function(item, _with_data) {
    var c = MochiKit.Style.getElementPosition(this.imgElement);
    var ec = MochiKit.Style.getElementPosition(this.element);
    var i = _with_data || this;
    if(item instanceof MochiKit.Maps__Schmap.Point) {
        // convert to MochiKit.Style.Coordinates
        c.x += Math.round((item.longitude - this.imgBounds.west) * i.zoomFactors.x);
        //c.y += Math.round((this.imgBounds.north - item.latitude) * i.zoomFactors.y);
        var absYPos = this.getYPosFromLat (item.latitude);
        absYPos = Math.round(absYPos * this.heightRatio);
        c.y += absYPos;
        return c;
    } else if(item instanceof MochiKit.Style.Coordinates) {
        // convert to MochiKit.Maps__Schmap.Point
        item = clone(item);
        item.x += (c.x - ec.x);
        item.y += (c.y - ec.y);
        return new MochiKit.Maps__Schmap.Point(
             this.imgBounds.north - item.y / i.zoomFactors.y,
             this.imgBounds.west + item.x / i.zoomFactors.x);
    } else if(item instanceof MochiKit.Maps__Schmap.Bounds) {
        // convert to [MochiKit.Style.Coordinates, MochiKit.Style.Dimensions]
        c.x += Math.round((item.west - this.imgBounds.west) * i.zoomFactors.x);
        c.y += Math.round((this.imgBounds.north - item.north) * i.zoomFactors.y);
        return [c, new MochiKit.Style.Dimensions(
             Math.round((item.east - item.west) * i.zoomFactors.x),
             Math.round((item.north - item.south) * i.zoomFactors.y))];
    } else if((item.length == 2) &&
              (item[0] instanceof MochiKit.Style.Coordinates) &&
              (item[1] instanceof MochiKit.Style.Dimensions)) {
        // convert to MochiKit.Maps__Schmap.Bounds
        var nw = this.convert(item[0], _with_data);
        return new MochiKit.Maps__Schmap.Bounds(
             nw.latitude - item[1].h / i.zoomFactors.y,
             nw.longitude,
             nw.latitude,
             nw.longitude + item[1].w / i.zoomFactors.x);
    } else {
        logWarning('Map.convert: unknown argument');
        return undefined;
    }
};

MochiKit.Maps__Schmap.Map.prototype.addItem = function(item) {
    if(item.__added__ !== undefined)
        item.__added__(this);
    else
        item.map = this;
    if(item.__display__ !== undefined)
        this._items.push(item);
};

MochiKit.Maps__Schmap.Map.prototype.hideMarkers = function() {
    this.markersElement.style.zIndex = 0;	
	this.markersElement.style.visibility = "hidden";
};

MochiKit.Maps__Schmap.Map.prototype.__display__ = function() {
    if(this.markersHidden) return;
    map(function(item) {item.__display__();}, this._items);
    this.markersElement.style.zIndex = 2;
	this.markersElement.style.visibility = "visible";
};

MochiKit.Maps__Schmap.Map.prototype.hideAll = function(hide) {
    if(hide) {
        this.markersHidden = true;
        this.hideMarkers();
    } else {
        this.markersHidden = false;
        this.__display__();
    }
};

MochiKit.Maps__Schmap.Map.prototype._panDragMove = function(event) {
    if(!this._pandrag_lock) try {
        this._pandrag_lock = true;
        var now = getElementPosition(event.mouse().client);
        var offset = getElementPosition(this._pandrag_last, now);
        logDebug('dragging by', offset.x, ',', offset.y);
        var pos = getElementPosition(this.imgElement);
        pos.x -= offset.x; pos.y -= offset.y;
        logDebug('dragging to', repr(pos));
        this._setCenter(pos);
        this._pandrag_last = now;
        this.__display__();
    } finally {
        this._pandrag_lock = false;
    }
    event.stop();
}

MochiKit.Maps__Schmap.Map.prototype._panDragEnd = function(event) {
    disconnect(this._pandrag_movehandler);
    disconnect(this._pandrag_releasehandler);
    //if(!this._pandrag_hidden)
    //    this.hideAll(false);
    logDebug('end of dragging pan');
}

MochiKit.Maps__Schmap.Map.prototype._panDrag = function(event) {
    //this._pandrag_hidden = this.markersHidden;
    //if(!this._pandrag_hidden)
    //    this.hideAll(true);
    //this._pandrag_moved = false;
    this._pandrag_lock = false;
    this._pandrag_last = event.mouse().client;
    this._pandrag_movehandler = connect(document.body, 'onmousemove',
                                        this, '_panDragMove');
    this._pandrag_releasehandler = connect(document.body, 'onmouseup',
                                           this, '_panDragEnd');
    event.stop();
}

MochiKit.Maps__Schmap.Point = function(lat, lon) {
    this.latitude = Number(lat);
    this.longitude = Number(lon);
};

MochiKit.Maps__Schmap.Point.prototype.__repr__ = function () {
    return "[Map Point at " + this.latitude + ',' + this.longitude + "]";
};

MochiKit.Maps__Schmap.Bounds = function(south, west, north, east) {
    if(south > north) {
        var tmp = south;
        south = north;
        north = tmp;
    }
    if(west > east) {
        var tmp = west;
        west = east;
        east = tmp;
    }
    this.west = west;
    this.south = south;
    this.east = east;
    this.north = north;
};

MochiKit.Maps__Schmap.Bounds.fromGeoRSS = function(georss) {
    // extract from xml node
    if(georss.textContent && georss.nodeName &&
       georss.nodeName.match(/box$/))
        georss = georss.textContent;
    else if(georss.object)
        georss = georss.object;
    var box = map(Number, georss.split(/ /));
    
    return new MochiKit.Maps__Schmap.Bounds(box[0], box[1], box[2], box[3]);
};

MochiKit.Maps__Schmap.Bounds.prototype.__repr__ = function () {
    return "[Map bounds: (" + this.south + ", " + this.east +
                   ") to (" + this.north + ", " + this.west + ")]";
};

MochiKit.Maps__Schmap.Bounds.prototype.getCenter = function() {
    return new MochiKit.Maps__Schmap.Point((this.north + this.south) / 2,
                                   (this.west + this.east) / 2);
};

MochiKit.Maps__Schmap.Bounds.prototype.contains = function(pb) {
    if(pb instanceof MochiKit.Maps__Schmap.Bounds) {
        return (pb.west >= this.west) && (pb.east <= this.east) &&
               (pb.south >= this.south) && (pb.north <= this.north);
    } else if(pb instanceof MochiKit.Maps__Schmap.Point) {
        return (pb.longitude >= this.west) && (pb.longitude <= this.east) &&
               (pb.latitude >= this.south) && (pb.latitude <= this.north);
    }
};

MochiKit.Maps__Schmap.Bounds.prototype.equals = function(b) {
    return (b.west == this.west) && (b.east == this.east) &&
           (b.south == this.south) && (b.north == this.north);
};

MochiKit.Maps__Schmap.Bounds.prototype.getWidth = function() {
    return Math.abs(this.east - this.west);
};

MochiKit.Maps__Schmap.Bounds.prototype.getHeight = function() {
    return Math.abs(this.north - this.south);
};

MochiKit.Maps__Schmap.Bounds.prototype.metersAtSouth = function() {
    //var earthRadius = 6378137 * Math.abs(Math.cos(this.south));
    //return earthRadius * Math.PI * this.getWidth() / 180;
    
    var convertToRadsFactor = 180 / Math.PI;
    var sinLat1 = Math.sin (this.south / convertToRadsFactor);
    var cosLat1 = Math.cos (this.south / convertToRadsFactor);
    var long1Rad = this.west / convertToRadsFactor;
    var long2Rad = this.east / convertToRadsFactor;
    var cosLongDiff = Math.cos (long2Rad - long1Rad);

    var l_dist = 6378137 * Math.acos((sinLat1 * sinLat1) + 
				        (cosLat1 * cosLat1 * cosLongDiff));
    return l_dist;
};

MochiKit.Maps__Schmap.Icon = function(url, dimensions, anchor) {
    this.image = url;
    this.dimensions = dimensions;
    this.anchor = anchor;
};

MochiKit.Maps__Schmap.Icon.prototype.create = function() {
    e = IMG({src:this.image, suppress:"TRUE"});
    //e.src = this.image;
    //e.width = this.dimensions.w; 
    //e.height = this.dimensions.h;
    e.style.position = 'absolute';
    e.style.zIndex = '23';
    return e;
};

MochiKit.Maps__Schmap.Icon.prototype.IEcreate = function() {
    e = MochiKit.DOM.DIV(null);
    MochiKit.Style.setElementDimensions(e, this.dimensions);
    MochiKit.Style.setStyle(e, {
            display: 'block',
            position: 'absolute',
            filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(" +
                "src='" + this.image + "',sizingMethod='scale')",
            'z-index': '23'});
    return e;
};

// yes, browser detection is evil, but this is the only browser stupid enough
// to be unable to display alpha PNGs, and I don't want to single out IE7
var _MSIE = navigator.userAgent.indexOf("MSIE");
if((_MSIE != -1) && (parseFloat(navigator.userAgent.substring(_MSIE+5))) < 7) {
    MochiKit.Maps__Schmap.Icon.prototype.create =
        MochiKit.Maps__Schmap.Icon.prototype.IEcreate;    
} else {
    delete MochiKit.Maps__Schmap.Icon.prototype.IEcreate;
}
delete _MSIE;

MochiKit.Maps__Schmap.Marker = function(point, icon) {
    this.point = point;
    this.icon = icon;
    this.map = null;
    this.element = this.icon.create();
    this.hidden = false;
    this.eventAttachPriority = 0;
};

MochiKit.Maps__Schmap.Marker._nextId = 1;

MochiKit.Maps__Schmap.Marker.prototype.__repr__ = function () {
    return "[Marker at " + repr(this.point) + "]";
};

MochiKit.Maps__Schmap.Marker.prototype.__added__ = function (map) {
    this.map = map;
    this.map.markersElement.appendChild(this.element);
    this.__display__();
};

MochiKit.Maps__Schmap.Marker.prototype.__display__ = function () {
    if(!this.map) return;
    if(!this.hidden)
        this.element.style.display = 'block';
	p = this.map.convert(this.point);
	var mp = this.map.markersElementPosition;
	p.x = p.x-mp.x;
	p.y = p.y-mp.y;
    //p = getElementPosition(this.map.convert(this.point), this.map.markersElement);
    p.x -= this.icon.anchor.x; p.y -= this.icon.anchor.y;
    setElementPosition(this.element, p);
};

MochiKit.Maps__Schmap.Marker.prototype.reposition = function(point) {
    this.point = point;
    this.__display__();
};

MochiKit.Maps__Schmap.Marker.prototype.setImage = function(url) {
    this.element.src = url;
    this.__display__();
};

MochiKit.Maps__Schmap.Marker.prototype.show = function() {
    this.element.style.display = 'block';
    this.hidden = false;
};

MochiKit.Maps__Schmap.Marker.prototype.hide = function() {
    this.element.style.display = 'none';
    this.hidden = true;
};

MochiKit.Maps__Schmap.Marker.prototype.__connect__ =
    function(ident, signal, objOrFunc, funcOrStr) {
    if(funcOrStr === undefined) {
        funcOrStr = objOrFunc;
        objOrFunc = this;
    }
    if(signal == 'click') {
        // 'onclick' doesn't work for some reason
        signal = 'mousedown';
    }
    disconnect(ident);
   var  id2 = connect(this.element, 'on'+signal, objOrFunc, funcOrStr);
    if(ident.connected !== undefined) {
        // newer MochiKit.Signal.Ident
        update(ident, id2);
    } else  {
          for(var i = 0; i < id2.length; i++) {
            // older MochiKit.Signal
            ident[i] = id2[i];
          }
    }
}

MochiKit.Maps__Schmap.Marker.prototype.listen = function(events) {
    logWarning('Marker.listen is deprecated');
};

MochiKit.Maps__Schmap.Marker.prototype.unlisten = function() {
    logWarning('Marker.unlisten is deprecated');
};
MochiKit.Maps__Schmap.Marker.prototype.getElement = function() {
        return this.element;
};

MochiKit.Signal.signal(window, "MochiMaps-load", MochiKit.Maps__Schmap);

