/* Copyright 2005 by
           Atte Timonen
           Tarmo Toikkanen
           Teemu Leinonen
           Lily Diaz
           Janne Pietarila
           
 Code snippets used from Fle3 (fle3.uiah.fi),
 credits go to the Fle3 Team.

 This file is part of the ImaNote product.

 ImaNote is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 ImaNote is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with ImaNote; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

var DEBUG=false
if (DEBUG) {
  var DEBUGform=document.createElement('form')
  var DEBUGfield=document.createElement('textarea')
  DEBUGform.appendChild(DEBUGfield)
  DEBUGfield.setAttribute("type", "text")
  DEBUGfield.setAttribute('cols', '92')
  DEBUGfield.setAttribute('rows', '40')
  document.getElementById('border').parentNode.appendChild(DEBUGform)
}
var panorateOn=false
var firstRun=true
var imageLink=document.getElementById("maplink");
var smallmapLink=document.getElementById("smallmap");
var mapContent=document.getElementById("bigmap_content")
var mapDrawer=new jsGraphics("mapimg")
var dragOn=false
var shownAnno=-1
var resizeOn=false
var borderline = document.getElementById('border');
var focusedAnnotation=-1 //-1==not in use, -2==already used, 
                         //see also useAnnoFocus
                         
var annotateLink=document.getElementById('annotate')
if (annotateLink&&annotateLink.href) 
  annotateLink.href=annotateLink.href.replace(/annotation_1.html/, 'annotation_add.html')

if (borderline)
  borderline.style.overflow='hidden'
if (imageLink){
  imageLink.href='javascript:void(0)'
  ToffsetX=20;
  ToffsetY=20;
  var physWidth=getScreenSizeX()-getParent(getParent(imageLink)).offsetLeft-ToffsetX
  var physHeight=getScreenSizeY()-getParent(getParent(imageLink)).offsetTop-ToffsetY
  if (!physWidth||!physHeight){
    physWidth=800
    physHeight=600
  }
  for (i=0;i<document.links.length;i++){
    document.links[i].href=document.links[i].href.replace(/width\=-?[0-9]*/, "width="+physWidth)
    document.links[i].href=document.links[i].href.replace(/height\=-?[0-9]*/, "height="+physHeight)
  }
  var drawmode=getAttr(imageLink,'made:relation_draw_mode')
  var useAnnoFocus=getAttr(imageLink, 'made:locate')
  var wholeWidth=parseInt(getAttr(imageLink,'made:image_width'))
  var dragNotes=parseInt(getAttr(imageLink,'made:note_dragging'))
  var hideWhenNotFocused=parseInt(getAttr(imageLink,'made:hide_notes_when_no_focus'))
  var wholeHeight=parseInt(getAttr(imageLink,'made:image_height'))
  var overviewWidth=parseInt(getAttr(imageLink,'made:overview_width'))
  var overviewHeight=parseInt(getAttr(imageLink,'made:overview_height'))
  var tileWidth=parseInt(getAttr(imageLink, 'made:tile_width')) 
  var tileHeight=parseInt(getAttr(imageLink, 'made:tile_height')) 
  var showAll=getAttr(imageLink, 'made:show_all')
  var a_id=getAttr(imageLink, 'made:a_id')
  doMapMove=getAttr(imageLink, 'made:do_mapmove')
  var absUrl=getAttr(imageLink, 'made:absolute_url')
  //TODO : check referrer correctly in all situations
  //var mapMoveOn=doMapMove.indexOf(document.URL.split('?')[0].substr(0,document.URL.lastIndexOf('/')))==-1
  var mapMoveOn=false
  if (firstRun){
    addListener(imageLink, "mousemove", mouseOverMap)
    addListener(imageLink, "mousedown", clickImage)
  }
}
var tilesX=Math.ceil((physWidth+(1+(physWidth%tileWidth)))/tileWidth+2)
var tilesY=Math.ceil((physHeight+(1+(physHeight%tileHeight)))/tileHeight+2)
if (borderline){
  borderline.style.width = physWidth;
  borderline.style.height = physHeight;
}
var magnif=parseInt(getAttr(imageLink,'made:magnification'))
var level=parseInt(getAttr(imageLink, "made:magnification_level"))
var centerX=parseInt(getAttr(imageLink,"made:center_x"))
var centerY=parseInt(getAttr(imageLink,"made:center_y"))
var newAnnotation=null //Is the user adding a new annotation
if (isNaN(centerX)||isNaN(centerY)){
  centerX=Math.floor(wholeWidth/2)
  centerY=Math.floor(wholeHeight/2)
}
centerX=Math.floor(centerX/magnif)
centerY=Math.floor(centerY/magnif)
var centerXOrig=centerX
var centerYOrig=centerY



//Colors to draw the annotation with:
var color1=getAttr(imageLink,'made:color1')
var color2=getAttr(imageLink,'made:color2')
//Whether to show annotation title on top of hotspot
var showTitleOverHotspot=parseInt(getAttr(imageLink, 'made:show_title_over_hotspot'))

var haveSmallmap=document.getElementById("locationRectangle")
if (haveSmallmap){
  smallmapLink.href='javascript:void(0)'
  var locationPainter=new jsGraphics("locationRectangle");
  var locationRectangle=document.getElementById("locationRectangle").style;
  var rectangleWidth=physWidth/wholeWidth*magnif*overviewWidth
  var rectangleHeight=physHeight/wholeHeight*magnif*overviewHeight
  smallbord=document.getElementById('smallmap_border')
  if (firstRun&&smallmapLink) addNBListener(smallmapLink, "mousedown", clickOvMap)
}
var CURSOR_DEFAULT=0
var CURSOR_RESIZE=1
var CURSOR_DRAG=2
var cursor=CURSOR_RESIZE


function Rectangle(x1, y1, x2, y2){
  this.x1=x1
  this.x2=x2
  this.y1=y1
  this.y2=y2
  this.getWidth=function(){
    return this.x2-this.x1
  }
  this.getHeight=function(){
    return this.y2-this.y1
  }
  this.setWidth=function(width){
    this.x2=this.x1+width
  }
  this.setHeight=function(height){
    this.y2=this.y1+height
  }
  this.equals=function(cmp){
    return (this.x1==cmp.x1&&this.y1==cmp.y1&&this.x2==cmp.x2&&this.y2==cmp.y2)
  }
}

//A single tile. These make the image.
var borderX=Math.ceil(wholeWidth/magnif/tileWidth)
var borderY=Math.ceil(wholeHeight/magnif/tileHeight)
var srcEmpty
function Tile(element, startX, startY){
  this.elem=element
  this.startX=startX
  this.startY=startY
  srcTemp=document.URL.split('?')[0]
  this.srcBase=srcTemp.replace(/\/[^\/]*html$/, "/")+'/tile_'
  srcEmpty=this.srcBase+'empty_with_dimensions'
  //Update the image
  this.setTileCoords=function(x,y){
    this.startX=x
    this.startY=y
    if (x<0||y<0||x>=borderX||y>=borderY) this.elem.src=srcEmpty
    else this.elem.src=this.srcBase+level+'_'+x+'_'+y
  }
}
var tiles = new Array(tilesX)
for (p=0;p<tilesX;p++){
  tiles[p]=new Array(tilesY)
}

var tileXOrig
var tileYOrig
var tileMoveX=0
var tileMoveY=0
var styleMoveX=0
var styleMoveY=0
var imageOffsetX=-physWidth/2-tileWidth
var imageOffsetY=-physHeight/2-tileHeight
//Build the image from tiles
function makeImage(){
  if (haveSmallmap){
    locationPainter.setColor("#ff0000");
    locationPainter.setStroke(2);
    locationPainter.drawRect(0, 0, rectangleWidth, rectangleHeight)
    locationPainter.paint()
    locationRectangle.left=overviewWidth/wholeWidth*centerX*magnif-rectangleWidth/2
    locationRectangle.top=overviewHeight/wholeHeight*centerY*magnif-rectangleHeight/2+1
  }
  x=centerX+imageOffsetX
  y=centerY+imageOffsetY
  tileXOrig=Math.floor(x/tileWidth)
  tileYOrig=Math.floor(y/tileWidth)
  tileX=Math.floor(x/tileWidth)
  tileY=Math.floor(y/tileHeight)
  styleMoveX=-((x+1000*tileWidth)%tileWidth)-tileWidth
  styleMoveY=-((y+1000*tileHeight)%tileHeight)-tileHeight
  mapContent.style.left=(styleMoveX)+'px'
  mapContent.style.top=(styleMoveY)+'px'

  for (y=0;y<tilesY;y++){
    for (x=0;x<tilesX;x++){
      tile=document.createElement('img')
      tile.style.borderStyle='none'
      tiles[x][y]=new Tile(tile, x+tileX, y+tileY)
      tiles[x][y].elem.style.width=tileWidth+'px'
      tiles[x][y].elem.style.height=tileHeight+'px'
      tiles[x][y].elem.style.position="absolute"
      tiles[x][y].elem.style.left=((x*tileWidth))+'px'
      tiles[x][y].elem.style.top=((y*tileHeight))+'px'
      tiles[x][y].setTileCoords(x+tileX, y+tileY)
      imageLink.appendChild(tile)
    }
  }
}

var rectMultX=overviewWidth/wholeWidth*magnif
var rectMultY=overviewHeight/wholeHeight*magnif
var rectOffsetX=-rectangleWidth/2
var rectOffsetY=-rectangleHeight/2+1
var updateFrequency=2
var lastTileMoveX=0
var lastTileMoveY=0
//Update the image position (it's being dragged)
function updateImage(){
  if (haveSmallmap){
    locationRectangle.left=rectMultX*centerX+rectOffsetX
    locationRectangle.top=rectMultY*centerY+rectOffsetY
  }
  x=centerX+imageOffsetX
  y=centerY+imageOffsetY
  tileX=Math.floor(x/tileWidth)
  tileY=Math.floor(y/tileHeight)
  styleMoveX=-((x+1000*tileWidth)%tileWidth)-tileWidth
  styleMoveY=-((y+1000*tileHeight)%tileHeight)-tileHeight
  if (tileX!=lastTileMoveX||tileY!=lastTileMoveY){
    for (y=0;y<tilesY;y++){
      for (x=0;x<tilesX;x++){
        tiles[x][y].setTileCoords(tileX+x, tileY+y)
      }
    }
    tileMoveX=(tileXOrig-tileX)*tileWidth
    tileMoveY=(tileYOrig-tileY)*tileHeight
    lastTileMoveX=tileX
    lastTileMoveY=tileY
  }
  mapContent.style.left=styleMoveX
  mapContent.style.top=styleMoveY
  //updateAnnos()
  if (newAnnotation!=null&&newAnnotation) newAnnotation.update()
  if (panorateOn||mapMoveOn){
    setTimeout("updateImage()", updateFrequency)
  }
}

function Annotation(index, element, coordElement, relationElement){
  this.index=index
  this.resizeBorder=8
  this.reDraw=false
  this.coords=new Array(4)
  this.windowCoords=new Array(4)
  this.element=element
  this.style=element.style
  this.coordElement=coordElement
  this.relationElement=relationElement
  this.visible=false
  this.id=element.getAttribute('id')
  if (this.id) this.idNum=parseInt(this.id.substr(1,this.id.length-1))
  this.isNew=this.id=='undefined'
  //Focus the annotation if the user followed a link to this specific annotation
  if (a_id) {
    if (this.id==a_id&&focusedAnnotation!=-2&&useAnnoFocus) 
      focusedAnnotation=this
  }
  if (this.isNew) newAnnotation=this
  
  //Style settings, used for optimization purposes
  this.oldTop=0
  this.oldLeft=0
  
  
  for (k=0;k<element.attributes.length;k++){
    if(element.attributes[k].name=='made:coordinates'){
      temp=element.attributes[k].value.split(',');
    }
    if(element.attributes[k].name=='made:writable'){
      this.writable=parseInt(element.attributes[k].value);
    }
    if(element.attributes[k].name=='made:iconurl'){
      this.iconUrl=element.attributes[k].value;
    }
    if(element.attributes[k].name=='made:title'){
      this.title=element.attributes[k].value;
    }
  }

  for (k=0;k<relationElement.attributes.length;k++){
    if(this.relationElement.attributes[k].name=='made:target_ids'){
      var relations_temp=this.relationElement.attributes[k].value
      if (relations_temp.length==2){ //"[]"
        this.relations=Array()
        break
      }
      this.relations=relations_temp.replace(/'| |\[|\]/g, "").split(',')
      break
    }
  }
/*  alert(this.relations+ ' foo:'+this.relations.length)
  for (x=0;x<this.relations.length;x++){
    alert("A"+this.relations[x]+"A")
  }*/
  
  for (r=0;r<4;r++){
    if (r==0) temp[r]=temp[r].substring(1,temp[r].length)
    if (r==3) temp[r]=temp[r].substring(0,temp[r].length-1)
    this.coords[r]=parseInt(temp[r]);
    this.coords[r]/=magnif
    if (r==0||r==2) this.windowCoords[r]=this.coords[r]+annoOffsetX+tileMoveX
    if (r==1||r==3) this.windowCoords[r]=this.coords[r]+annoOffsetY+tileMoveY
  }
  this.width=this.coords[2]-this.coords[0]
  this.height=this.coords[3]-this.coords[1]
  //Use this for resetting original location/dimensions if data is not saved
  this.origRect=new Rectangle(this.coords[0], this.coords[1], this.coords[2], this.coords[3])

  //Add img element for icon
  if (this.iconUrl){
    this.icon=document.createElement('img')
    this.icon.style.visibility='visible'
    this.icon.style.borderStyle='none'
    this.icon.src=this.iconUrl+'/'
    hei=this.icon.height
    wid=this.icon.width
    ratio=this.icon.width/this.icon.height
    while(hei+5>=this.height||wid+5>=this.width){
      hei-=1
      wid-=ratio
    }
    //this.icon.width=1
    //this.icon.height=1
    this.icon.width=wid
    this.icon.height=hei
    this.icon.style.top=3
    this.icon.style.left=3
    this.icon.style.position='absolute'
    this.coordElement.appendChild(this.icon)
    this.icon.style.visibility=this.coordElement.style.visibility
    addNBListener(this.icon, "mousemove", mouseOverIcon)
    addNBListener(this.icon, "mousedown", mouseClickIcon)
/*    addListener(this.coordElement, "mousemove", mouseOverMap)
    addListener(this.coordElement, "mousedown", clickImage)*/
  }
  this.links=this.element.getElementsByTagName("a")
  for (i=0;i<this.links.length;i++){
    if (this.links[i].className=="moveto"&&this.writable){
      addNBListener(this.links[i], "click", activateNoteMove)
    }
  }


  this.painter=new jsGraphics('a'+this.id)


  this.resetLocation=function(){
    if (!this.isNew){
      this.coords[0]=this.origRect.x1
      this.coords[1]=this.origRect.y1
      this.coords[2]=this.origRect.x2
      this.coords[3]=this.origRect.y2
      if (this.width!=this.origRect.getWidth()||this.height!=this.origRect.getHeight()){
        this.width=this.origRect.getWidth()
        this.height=this.origRect.getHeight()
        this.reDraw=true
      }
      this.update()
    }
  }

  this.resetIcon=function(){
    if(this.icon){
      this.coordElement.removeChild(this.coordElement.firstChild);
      this.icon=document.createElement('img')
      this.icon.style.borderStyle='none'
      this.icon.src=this.iconUrl+'/'
      ratio=this.icon.width/this.icon.height
      hei=this.icon.height
      wid=this.icon.width
      while(hei+5>=this.height||wid+5>=this.width){
        hei-=1
        wid-=ratio
      }
      this.icon.width=wid
      this.icon.height=hei
      this.icon.style.top=3
      this.icon.style.left=3
      this.icon.style.position='absolute'
      this.coordElement.insertBefore(this.icon, this.coordElement.firstChild)
      addNBListener(this.icon, "mousemove", mouseOverIcon)
      addNBListener(this.icon, "mousedown", mouseClickIcon)
    }
  }


  this.saveLocation=function(){
    this.origRect.x1=this.coords[0]
    this.origRect.y1=this.coords[1]
    this.origRect.x2=this.coords[2]
    this.origRect.y2=this.coords[3]
    this.resetIcon()

  }
  this.getRectangle=function(){
    return new Rectangle(this.coords[0], this.coords[1], this.coords[2], this.coords[3])
  }
  
  this.draw=function(width,height){
    //Actually draws the rectangle
    this.painter.clear()
    if (color1==color2){
      this.painter.setColor('#'+color1)
    }
    else{
      this.painter.setColor('#'+color1);
      if (this.writable) this.painter.drawRect(1, 1 ,this.width-4 ,this.height-4)
      else this.painter.drawRect(0, 0, this.width-1, this.height-1)
      this.painter.setColor('#'+color2);
    }
    if (this.writable) this.painter.drawRect(-2,-2,this.width+2,this.height+2)
    else this.painter.drawRect(-1,-1,this.width+1, this.height+1)
    if (showTitleOverHotspot) {
      this.painter.setFont("helvetica", "12px", Font.BOLD)
      this.painter.drawStringRect(this.title, -40,-15, this.width+80,"center")
    }
    if (annos&&this.relations.length>0){
      for (var i=0;i<annos.length;i++){
        for (var j=0;j<this.relations.length;j++){
          if(annos[i].id==this.relations[j]){
            
            midx=this.windowCoords[0]+this.width/2
            midy=this.windowCoords[1]+this.height/2
            rmidx=annos[i].windowCoords[0]+annos[i].width/2
            rmidy=annos[i].windowCoords[1]+annos[i].height/2
            if (drawmode=='traditional')
              this.painter.drawLine(this.width/2,this.height/2,this.width/2+rmidx-midx,this.height/2+rmidy-midy)
            else{
              //coordinates of the rectangle centers, as this.painter sees them
              x1=this.width/2
              y1=this.height/2
              x2=rmidx-this.windowCoords[0]
              y2=rmidy-this.windowCoords[1]
              linewidth=x2-x1
              lineheight=y2-y1
              if (Math.abs(linewidth)>Math.abs(lineheight)){ 
                //use 2 horizontal lines with 1 vertical line between them
                widthoffs=Math.floor(this.width/2+annos[i].width/2)
                if (linewidth>0) {
                  linewidth-=widthoffs+3
                  x1=this.width
                }
                  else { 
                    x1=-2
                    linewidth+=widthoffs+2
                  }
                this.painter.drawLine(x1,y1,x1+linewidth/2,y1);
                this.painter.drawLine(x1+linewidth/2,y1,x1+linewidth/2,y1+lineheight);
                this.painter.drawLine(x1+linewidth/2,y1+lineheight,
                    x1+linewidth,y1+lineheight);
              }
              else { //use 2 vertical lines with 1 horizontal line between them
                heightoffs=this.height/2+annos[i].height/2
                if (lineheight>0) {
                  lineheight-=heightoffs+3
                  y1=this.height
                }
                else {
                  y1=-2
                  lineheight+=heightoffs+2
                }
                this.painter.drawLine(x1,y1,x1,y1+lineheight/2);
                this.painter.drawLine(x1,y1+lineheight/2,x1+linewidth,y1+lineheight/2);
                this.painter.drawLine(x1+linewidth,y1+lineheight/2,
                    x1+linewidth,y1+lineheight);
              }
              break;
            }
          }
        }
      }
    }
    this.painter.paint()
  }

  this.doesCover=function(x,y){
    x-=styleMoveX
    y-=styleMoveY
    return x >= this.windowCoords[0] && x <= this.windowCoords[2] && y >= this.windowCoords[1]  && y <= this.windowCoords[3]
  }

  this.isCloseTo=function(x,y){
    var tolerance=10
    x-=styleMoveX
    y-=styleMoveY
    isClose = x >= this.windowCoords[0]-tolerance && x <= this.windowCoords[2]+tolerance && y >= this.windowCoords[1]-tolerance && y <= this.windowCoords[3]+tolerance
    if (getBrowser()=='opera'){
      return isClose || (x >= this.windowCoords[2] && x <= this.windowCoords[2]+this.element.clientWidth && y >= this.windowCoords[1] && y <= this.windowCoords[1]+this.element.clientHeight)
    }
    return isClose
  }

  //Should we go to resize mode if the user clicks now?
  this.shouldResizeXY=function(x,y){
    x-=styleMoveX
    y-=styleMoveY
    return x >= this.windowCoords[2]-this.resizeBorder && x <= this.windowCoords[2] && y >= this.windowCoords[3]-this.resizeBorder && y <= this.windowCoords[3]
  }
  
  this.paint=function(){
    for (r=0;r<4;r++){
      if (r==0||r==2) this.windowCoords[r]=this.coords[r]+annoOffsetX+tileMoveX
      if (r==1||r==3) this.windowCoords[r]=this.coords[r]+annoOffsetY+tileMoveY
    }
    x1=this.windowCoords[0];
    y1=this.windowCoords[1];
    x2=this.windowCoords[2];
    y2=this.windowCoords[3];
    if (!this.writable) this.painter.setStroke(1);
    else this.painter.setStroke(2)
    this.draw(x2-x1,y2-y1)
    this.resetIcon()
  }

  this.setDimensions=function(width, height){
    if (width!=this.width||height!=this.height){
      this.width=width
      this.height=height
      if (this.width<0){
        this.width*=-1
        this.coords[2]=this.origRect.x1
        this.coords[0]=this.coords[2]-this.width
      }
      if (this.height<0){
        this.height*=-1
        this.coords[3]=this.origRect.y1
        this.coords[1]=this.coords[3]-this.height
      }
      this.coords[2]=this.coords[0]+this.width
      this.coords[3]=this.coords[1]+this.height
      this.reDraw=true
    }
  }
  this.save=function(){
    if (!this.isNew){
      updateUrl='updateAnnotationPosition?a_id='+this.id+'&newX1='+(Math.round(this.coords[0]))+'&newY1='+(Math.round(this.coords[1]))+'&level='+level+'&width='+(Math.round(this.width))+'&height='+(Math.round(this.height))
//      alert("http://church.uiah.fi:9673/edam/spaghettimonster/"+updateUrl)
      if (window.location) window.location=updateUrl
      else if (window.navigate) window.navigate(updateUrl)
      hilightAnno(this)
      dragOn=false
      resizeOn=false

      
      if (draggedAnno!=0){
        draggedAnno.saveLocation()
        draggedAnno=0
      }
      if (resizedAnnotation!=0){
        resizedAnnotation.saveLocation()
        resizedAnnotation=0
      }
      if (movedNote){
        movedNote.saveLocation()
        movedNote=0
      }
    }

    for (var i=0;i<annos.length;i++){
      annos[i].paint()

    }
  }

  this.setPosition=function(x1, y1){
    this.coords[0]=x1
    this.coords[1]=y1
    this.coords[2]=x1+this.width
    this.coords[3]=y1+this.height
  }
  
  this.deleteAnno=function(){
    this.painter.clear()
  }

  this.update=function(){
    //Just sets the position, doesn't redraw the rectangle
    this.windowCoords[0]=this.coords[0]+annoOffsetX+tileMoveX
    this.windowCoords[1]=this.coords[1]+annoOffsetY+tileMoveY
    this.windowCoords[2]=this.coords[2]+annoOffsetX+tileMoveX
    this.windowCoords[3]=this.coords[3]+annoOffsetY+tileMoveY
    x1=this.windowCoords[0];
    y1=this.windowCoords[1];
    x2=this.windowCoords[2];
    y2=this.windowCoords[3];
    //Update rect position
    if (this.oldTop!=y1){
      this.coordElement.style.top=y1
      this.oldTop=y1
    }
    if (this.oldLeft!=x1){
      this.coordElement.style.left=x1
      this.oldLeft=x1
    }
    if (this.reDraw){
      this.draw(x2-x1, y2-y1)
      this.reDraw=false
    }
    //Update popup position
    if(this.visible){
      var popupOnRightSide=true
      offset=-199
      if (getBrowser()=='ie') offset=-176
      if (x2+styleMoveX>physWidth+offset){
        if (this.windowCoords[0]+offset<-styleMoveX){
          //Annotation doesnt fit well to either side of rectangle
          this.style.left=x1+2
        }
        else {
          this.style.left=x1+offset;
          popupOnRightSide=false
        }
      }
      else this.style.left=x2+1;
      annoArray=new Array();
      outer: for (m=0;m<annos.length;m++){
        for (y=0;y<4;y++){
          if (annos[m].coords[y]!=this.coords[y]) continue outer
        }
        annoArray.push(annos[m])
      }
      function compareAnnos(a, b){
        return a.idNum-b.idNum
      }
      annoArray.sort(compareAnnos)
      var annoIndex=0
      for (m=0;m<annoArray.length;m++){
        if (annoArray[m].id==this.id){
          annoIndex=m
        }
        //Make it possible to move an
        //annotation that is writable but not on top of stack
        if (annoArray[m].writable&&!annoArray[0].writable){
          shownAnno=annoArray[m]
        }
      }
      this.zIndex=annoArray.length-annoIndex
      this.style.zIndex=this.zIndex
      spaceX=15 //How many pixels to leave between annotation pop-ups that are
      //on top of each other
      spaceY=15
      if (popupOnRightSide){
        this.style.left=parseInt(this.style.left)+annoIndex*spaceX
      }
      else {
        this.style.left=parseInt(this.style.left)-annoIndex*spaceX
      }
      if (y1+styleMoveY+annoIndex*spaceY>physHeight-this.element.clientHeight){
        this.style.top=physHeight-this.element.clientHeight-styleMoveY-2
      }
      else this.style.top=y1+annoIndex*spaceY
    }
  }
}

var browser
//Find out about user's browser
function getBrowser(){
  if (browser!=undefined) return browser
  var ua=navigator.userAgent.toLowerCase();
  if(ua.indexOf("opera")!=-1){
    browser='opera'
    return browser
  }
  else if (ua.indexOf("msie")!=-1){
    browser='ie'
    return browser
  }
  else if (ua.indexOf("safari")!=-1){
    browser="safari"
    return browser
  }
  else{
    browser='mozilla'
    return browser
  }
}

function elemFocus(event){
  var node=getEventTarget(event)
  while (node.className!='annotation'){
    node=node.parentNode;
  }
  for (l=0;l<annos.length;l++){
    if (annos[l].zIndex) annos[l].style.zIndex=annos[l].zIndex
  }
  node.style.zIndex='100'
}

var annoOffsetX
var annoOffsetY
var annos;
//Create the Annotation-structures (called only once)
function getAnnos(annoDiv, fromXML){
  deleteAnnos()
  annos=new Array();
  annoTempElems=annoDiv.childNodes
  annoElems=new Array() //Elements that contain annotation data
  annoCoordElems=new Array() //Elements that are used to store annotation 
                             //locations
                             //alert(annoDiv.childNodes[0].childNodes.length)
  annoRelationElems=new Array()
  for (i=0;i<annoTempElems.length;i++){ //All annotations
//for (k=0;k<annoTempElems[0].childNodes.length;k++){
//  alert(annoTempElems[0].childNodes[k].nodeType)
//}
//alert(annoDiv.childNodes[0])
//listAttributes(annoDiv.childNodes[0])
//alert(annoTempElems[i].nodeName)
    if (annoTempElems[i].nodeType==1){ //DIV annotationData 
      dataElems=annoTempElems[i].childNodes
      
      if (getBrowser()=='ie'){
        if (fromXML){
          for (k=0;k<dataElems.length;k++){
            annoCoordElems.push(dataElems[k].childNodes[0])
            annoElems.push(dataElems[k].childNodes[1])
            annoRelationElems.push(dataElems[k].childNodes[2])
          }
        }
        else{
          annoCoordElems.push(dataElems[0])
          annoElems.push(dataElems[1])
          annoRelationElems.push(dataElems[2])

        }
      }
      else if (getBrowser()=='opera' && fromXML){
        for (k=0;k<dataElems.length;k++){
          if (hasAttr(dataElems[k], 'CLASS') && getAttr(dataElems[k], 'CLASS')=='annotationData'){
            annoCoordElems.push(dataElems[k].childNodes[1])
            annoElems.push(dataElems[k].childNodes[3])
            annoRelationElems.push(dataElems[k].childNodes[5])
          }
        }
      }
      
      
      else if (getBrowser()=="safari"&&fromXML){
        for (k=0;k<dataElems.length;k++){
          if (k%2==1){
            annoCoordElems.push(dataElems[k].childNodes[1])
            annoElems.push(dataElems[k].childNodes[3])
            annoRelationElems.push(dataElems[k].childNodes[5])
          }
        }
      }
      else {
        annoCoordElems.push(dataElems[1])
        annoElems.push(dataElems[3])
        annoRelationElems.push(dataElems[5])
      }
    }
  }
  for (j=0;j<annoElems.length;j++){
    annos[j]=new Annotation(j, annoElems[j], annoCoordElems[j], annoRelationElems[j])
  }
  for (j=0;j<annoElems.length;j++){
    annos[j].paint()
    annos[j].resetIcon()
  }
  if (focusedAnnotation!=-1&&focusedAnnotation!=-2) {
    focusedAnnotation.visible=true
    hilightAnno(focusedAnnotation)
  }
  updateAnnos()
  if (firstRun){
    addVisibilityListeners()  
    firstRun=false
  }
}

var annosVisible=true
function hideAnnotations(event){
  if (!annosVisible) return
  annosVisible=false
  if (event!=undefined){
    target=getEventTarget(event)
    if (target==smallmapLink||target.parentNode==smallmapLink){
      width=overviewWidth
      height=overviewHeight
    }
    else{
      width=physWidth
      height=physHeight
    }
    if (getX(event)<=0||getX(event)>=width||getY(event)<=0||getY(event)>=height){
      for (n=0;n<annos.length;n++){
        //If we're adding new annotation, leave it visible
        if (n==annos.length-1&&annos[n].id=='undefined') continue
        //Don't hide focused annotation
        if (focusedAnnotation!=-2&&
          focusedAnnotation!=-1&&
          focusedAnnotation.id==annos[n].id) continue
        if (annos[n].visible) lolightAnno(annos[n])
        annos[n].coordElement.style.visibility="hidden"
      }
      if (draggedAnno){
        draggedAnno.resetLocation()
      }
      if (resizedAnnotation){
        resizedAnnotation.resetLocation()
      }
    }
  }
  else {
    if (!annos) return
    for (n=0;n<annos.length;n++){
      if (n==annos.length-1&&annos[n].id=='undefined') continue
        annos[n].coordElement.style.visibility="hidden"
    }
  }
}

function showAnnotations(event){
  if (annosVisible) return
  annosVisible=true
  for (n=0;n<annos.length;n++){
    annos[n].coordElement.style.visibility='visible'
  }
}

function addAnnotation(event){
  form=getEventTarget(event)
  newAnno=annos[annos.length-1]
  createHiddenInput(form, "coord_x_1", Math.round(newAnno.coords[0]*magnif))
  createHiddenInput(form, "coord_y_1", Math.round(newAnno.coords[1]*magnif))
  createHiddenInput(form, "coord_x_2", Math.round(newAnno.coords[2]*magnif))
  createHiddenInput(form, "coord_y_2", Math.round(newAnno.coords[3]*magnif))
  inputCenterCoords(event)
  return true
}

function inputCenterCoords(event){
  target=getEventTarget(event)
  elems=target.elements;
  for(i=0;i<elems.length;i++){
    name=elems[i].getAttribute('name')
    if (name=='center_x'||name=='center_y'){
      target.removeChild(elems[i])
      i--
    }
  }
  createHiddenInput(target, "center_x", Math.round(centerX*magnif))
  createHiddenInput(target, "center_y", Math.round(centerY*magnif))
}

//Update all annotation positions and dimensions
function updateAnnos(){
  for (i=0;i<annos.length;i++){
    annos[i].update()
  }
}
function deleteAnnos(){
  if (annos){
    for (i=0;i<annos.length;i++){
      annos[i].deleteAnno()
    }
  }
}

//Hilight annotation
function hilightAnno(anno){
  if (!anno.isNew){
    addNBListener(anno.element, "mouseover", elemFocus)
    anno.style.visibility='visible'
  }
}

//Lolight annotation
function lolightAnno(anno){
  anno.style.visibility='hidden'
  removeListener(anno.element, "mouseover", elemFocus)
}

var shownAnno=-1
//React to mouse position (hilight annos, etc.)
function mouseOverMap(event)
{
  if (movedNote) return
  mapMoveOn=false;
  cursorResize=false;
  x=getCoord(event, true, true)
  y=getCoord(event, false, true)
  if (!annosVisible) showAnnotations()
  for (i=0;i<annos.length;i++){
    if (annos[i].doesCover(x,y)){ //annotation found
      if (focusedAnnotation) {
        if (focusedAnnotation.index==annos[i].index) focusedAnnotation=-2
      }
      if(annos[i].shouldResizeXY(x,y)&&annos[i].writable&&dragNotes){
        cursorResize=true
        if (cursor!=CURSOR_RESIZE) imageLink.style.cursor="se-resize"
        cursor=CURSOR_RESIZE
      }
      if (annos[i].visible){
        hilightAnno(annos[i])
        if (-1==shownAnno){
          shownAnno=annos[i]
        }
      }
      else{
        annos[i].visible=true
        shownAnno=annos[i]
        hilightAnno(annos[i]);
      }
    } // Not on top of annotation i
    else if (annos[i].visible&&!annos[i].isCloseTo(x,y)){
      if (dragOn&&i==draggedAnno.index) {
        dragOn=false
        //Reset annotation position because new position wasn't saved
        draggedAnno.resetLocation()
        draggedAnno=0
      }
      if (resizeOn&&i==resizedAnnotation.index){
        resizedAnnotation.resetLocation() 
        resizeOn=false
        resizedAnnotation=0
      }
      annos[i].visible=false;
      shownAnno=-1
      lolightAnno(annos[i]);
    }
  }
  if (focusedAnnotation!=-1&&focusedAnnotation!=-2) {
    //focusedAnnotation.visible=true
    hilightAnno(focusedAnnotation)
  }
  updateAnnos();
  if (!cursorResize&&cursor!=CURSOR_DEFAULT){
    cursor=CURSOR_DEFAULT
    imageLink.style.cursor="default"
  }
}

function clickImage(event){
  x=getX(event)
  y=getY(event)
  preventDefault(event)
  if (DEBUG){
    DEBUGfield.value+='X: '+x+'Y: '+y+'\n'
  }
  if (movedNote){
    movedNote.setPosition(xWinToWorld(x)-movedNote.width/2,yWinToWorld(y)-movedNote.height/2)
    movedNote.update()
    movedNote.save()
    movedNote=false
    imageLink.style.cursor='default'
  }
  else{
    removeListener(imageLink, "mousemove", mouseOverMap)
    if (focusedAnnotation!=-1&&focusedAnnotation!=-2) {
      lolightAnno(focusedAnnotation)
      focusedAnnotation.visible=false
      focusedAnnotation=-2
    }
    //Mouse is over annotation
    if (dragOn||shownAnno!=-1){
      //lolight all annotations
      for (l=0;l<annos.length;l++){ 
        lolightAnno(annos[l])
      }
      i=dragOn?draggedAnno.index:shownAnno.index
      if (!annos[i].writable||!dragNotes) {
        hilightAnno(annos[i])
        mouseOverMap(event)
        addListener(imageLink, "mousemove", mouseOverMap)
        return
      }
      if (annos[i].shouldResizeXY(x,y)){
        resizeStart(event, annos[i])
        return
      }
      if (dragNotes) dragStart(event)
      return
    }
    else{ //Mouse is not over annotation
      panorateStart(event)
      return
    }
  }
}

function clickOvMap(event){
  removeListener(smallmapLink, "mousemove", ovMove)
  removeListener(imageLink, "mousemove", mouseOverMap)
  removeListener(smallmapLink, "mousedown", clickOvMap)
  addListener(smallmapLink, "mousemove", ovMove)
  addListener(document, "mouseup", ovStop)
  mapMoveStart()
  panorateOn=true
  ovMove(event)
  updateImage()
}

ovMultX=wholeWidth/magnif/overviewWidth
ovMultY=wholeHeight/magnif/overviewHeight
function ovMove(event){
  preventDefault(event)
  //centerX=getX(event)*ovMultX
  //centerY=getY(event)*ovMultY
  centerX=getCoord(event, true, false)*ovMultX
  centerY=getCoord(event, false, false)*ovMultY
}

function ovStop(event){
  preventDefault(event)
  removeListener(smallmapLink, "mousemove", ovMove)
  removeListener(document, "mouseup", ovStop)
  addNBListener(smallmapLink, "mousedown", clickOvMap)
  addListener(imageLink, "mousemove", mouseOverMap)
  mapMoveStop()
}


var dragX=0
var dragY=0
var dragStartX=0
var dragStartY=0
var draggedAnno=0
//Start dragging an annotation (or the map)
function dragStart(event){
  dragX=getCoord(event, true, true)
  dragY=getCoord(event, false, true)
  i=dragOn?draggedAnno.index:shownAnno.index
  draggedAnno=annos[i]
  dragStartX=draggedAnno.coords[0]
  dragStartY=draggedAnno.coords[1]
  addListener(imageLink, "mousemove", dragMove)
  addListener(document, "mouseup", dragStop)
  lolightAnno(annos[i])
  annos[i].visible=false
  draggedAnno.update();
  dragOn=true
}

//Drag an annotation
function dragMove(event){
  x=getCoord(event, true, true)
  y=getCoord(event, false, true)
  target=getEventTarget(event)
  draggedAnno.setPosition(dragStartX+(x-dragX), dragStartY+(y-dragY))
  draggedAnno.update()
}

//Stop dragging an annotation
function dragStop(event){
  //Do not use x and y coords from this event, they might be coming from
  //annotation id-div instead of image, which results in wrong coords.
  removeListener(imageLink, "mousemove", dragMove)
  removeListener(document, "mouseup", dragStop)
  addListener(imageLink, "mousemove", mouseOverMap)
  if(!draggedAnno.getRectangle().equals(draggedAnno.origRect)){
    draggedAnno.save()
  }
  mouseOverMap(event)
}

var resizeStartX=0
var resizeStartY=0
var resizedAnnotation=0
function resizeStart(event, annotation){
  resizedAnnotation=annotation
  resizeOn=true
  resizeStartX=getCoord(event, true, true)
  resizeStartY=getCoord(event, false, true)
  addListener(imageLink, "mousemove", resizeMove)
  addListener(document, "mouseup", resizeStop)
}

function resizeMove(event){
  x=getCoord(event, true, true)
  y=getCoord(event, false, true)
  resizedAnnotation.setDimensions(resizedAnnotation.width+x-resizeStartX, resizedAnnotation.height+y-resizeStartY)
  resizedAnnotation.update()
  resizeStartX=getCoord(event, true, true)
  resizeStartY=getCoord(event, false, true)
}

function resizeStop(event){
  removeListener(imageLink, "mousemove", resizeMove)
  removeListener(document, "mouseup", resizeStop)
  addListener(imageLink, "mousemove", mouseOverMap)
  if(!resizedAnnotation.getRectangle().equals(resizedAnnotation.origRect)){
    resizedAnnotation.save()
  }

}

var panorX=0
var panorY=0
//Start dragging the map
function panorateStart(event){
  preventDefault(event)
  document.body.style.cursor="move"
  imageLink.style.cursor="move"
  panorX=getX(event)
  panorY=getY(event)
  addListener(document, "mousemove", panorateMove)
  addListener(document, "mouseup", panorateStop)
  panorateOn=true
  mapMoveStart()
  updateImage()
}

//Drag the map
function panorateMove(event){
  x=getCoord(event, true, true)
  y=getCoord(event, false, true)
  centerX-=x-panorX
  centerY-=y-panorY
  panorX=x
  panorY=y
}

//Stop dragging the map
function panorateStop(event){
  preventDefault(event)
  imageLink.style.cursor="default"
  document.body.style.cursor="default"
  removeListener(document, "mousemove", panorateMove)
  removeListener(document, "mouseup", panorateStop)
  addListener(imageLink, "mousemove", mouseOverMap)
  mapMoveStop()
}
//MapMove-functions are used py panorate and ovdrag
function mapMoveStart(){
  if (focusedAnnotation!=-1&&focusedAnnotation!=-2) {
    lolightAnno(focusedAnnotation)
    focusedAnnotation.visible=false
    focusedAnnotation=-2
  }
  hideAnnotations()
  removeVisibilityListeners()
}
function mapMoveStop(){
  cntrX=Math.floor(centerX*magnif)
  cntrY=Math.floor(centerY*magnif)
  panorateOn=false
  for(i=0;i<document.links.length;i++){
    document.links[i].href=document.links[i].href.replace(/center_x\=-?[0-9]*/, "center_x="+cntrX)
    document.links[i].href=document.links[i].href.replace(/center_y\=-?[0-9]*/, "center_y="+cntrY)
  }
  updateAnnos()
  showAnnotations()
  addVisibilityListeners()
  if (newAnnotation==null||!newAnnotation) setAnnoSrc(cntrX, cntrY, level)
}

getBrowser()
makeImage();
annoOffsetX=physWidth/2-centerXOrig-styleMoveX
annoOffsetY=physHeight/2-centerYOrig-styleMoveY
getAnnos(document.getElementById("annotations"), false)
if (newAnnotation==null||!newAnnotation) setAnnoSrc(Math.round(centerX*magnif),Math.round(centerY*magnif),level);  

function moveMap(){
  if (mapMoveOn){
    updateImage()
    setTimeout('moveCenterCoords()', 20)
    setTimeout('mapMoveOn=false', 5000)
  }
}

function moveCenterCoords(){
  centerX+=0.25
  centerY+=0.25
  if (mapMoveOn) setTimeout('moveCenterCoords()', 20)
}

moveMap()

function processReqChange() {
  if (req.readyState == 4 && req.status==200) {
/*  
    oldElem=document.getElementById('annotations')
    if (oldElem){
      par=getParent(oldElem)
      alert(par)
      par.replaceChild(req.responseXML, oldElem)
alert('foo')
    }
      elem=document.getElementById('annotations')*/
      //alert(document.getElementById('annotations').innerHTML)
      document.getElementById('annotations').innerHTML=req.responseText
      getAnnos(document.getElementById('annotations'), true)
  }
}
function setAnnoSrc(centerx, centery, level){
  var url=''
  if (getBrowser()=='opera'){
    url=absUrl+'/'
  } 
  loadUrl(url+'getAnnotations.html?center_x='+centerx+'&center_y='+centery+'&level='+level+'&width='+physWidth+'&height='+physHeight+'&show_all='+showAll)
}
function removeVisibilityListeners(){
  if (!hideWhenNotFocused) return;
  if (haveSmallmap){
    removeListener(smallmapLink, 'mouseout', hideAnnotations)
    removeListener(smallmapLink, 'mouseover', showAnnotations)
  }
  removeListener(imageLink, 'mouseout', hideAnnotations)
  removeListener(imageLink, 'mouseover', showAnnotations)
}
function addVisibilityListeners(){
  if (!hideWhenNotFocused) return;
  if(haveSmallmap){ 
    addListener(smallmapLink, 'mouseout', hideAnnotations)
    addListener(smallmapLink, 'mouseover', showAnnotations)
  }
  addListener(imageLink, 'mouseout', hideAnnotations)
  addListener(imageLink, 'mouseover', showAnnotations)
}
function xWinToWorld(x){
  return x-tileMoveX-styleMoveX-annoOffsetX
}
function yWinToWorld(y){
  return y-tileMoveY-styleMoveY-annoOffsetY
}

function keyPress(event){
  var key=0
  if (getBrowser()=='ie') var key=event.keycode
  else key=event.which
  if (key==27&&movedNote){
    movedNote=false
    imageLink.style.cursor='default'
    document.body.style.cursor='default'
  }

}
if (!dragNotes) document.onkeydown=keyPress

var movedNote=false
function activateNoteMove(event){
  link=event.target
  imageLink.style.cursor="crosshair"
  id=link.parentNode.getAttribute('id')
  for (i=0;i<annos.length;i++){
    if(annos[i].id==id) {
      movedNote=annos[i]
      break
    }
  }
  lolightAnno(movedNote)
  shownAnno=-1

  return false
}
function mouseOverIcon(event){
  mouseOverMap(event)
}
function mouseClickIcon(event){
  clickImage(event)
}
