/*
 * Author: Przemek Aksamit <extaliones@gmail.com>
 */
var map = null;
var items = [];
var selected = null;
var selected_item = null;
var cursor;


initMap = function(){
  map = new Map();
  for(var x = 0; x < streets.length; x++)
    items.push(new Item(streets[x], x));
  cursor = $('#cursor');
  $('#map_search').keyup(function(e){
    var regexp =  new RegExp(this.value,'i');
    for(var x = 0; x < items.length; x++){
      items[x].test(regexp);
    }
  });
  map.set_mode('zoomin');
  map.update_pine();
}

Map = $.klass({
  initialize: function(){
    var small = this.createMapLayer({x: 6, y: 7, dir: 'small', index: 0});
    var medium = this.createMapLayer({x: 18, y: 21, dir: 'medium', index: 1});
    var larg = this.createMapLayer({x: 36, y: 42, dir: 'full', index: 2});
    maps = [small, medium, larg];
    actual = 0;
    maps[actual].fillVisible();
    $(document).mouseup(function(e){
      for(var x = 0; x < 3; x++) maps[x].map_move = false;
    });
    $('#map').mousewheel(function(e,delta){
      e.preventDefault();
      if ($.browser.opera) delta = delta > 0 ? -1 : 1; 
      var x = e.pageX - this.offsetLeft;
      var y = e.pageY - this.offsetTop;
      map.zoom(x,y, delta > 0);
    });
  },
  createMapLayer: function(opts){
    var map = document.createElement('div');
    opts.div = $(map);
    $("#map").append(map);
    return $(map).attachAndReturn(MapLayer, opts)[0];
  },
  center_zoom: function(zoom){
    map.zoom(300,350,zoom);
  },
  zoom: function(xx, yy, zoom){
    var prev = maps[actual];
    if(zoom){//zoom in
      if(actual + 1 > 2) return;
      actual++;
    }else{
      if(actual - 1 < 0) return; 
      actual--;
    }
    //if(actual == 0) map.set_mode('zoomin');
    //if(actual == 2) map.set_mode('move');
    var x = (prev.x - xx) / prev.count_x;
    var y = (prev.y - yy) / prev.count_y;
    var am = maps[actual];
    var n_x = (x * am.count_x) + xx;
    var n_y = (y * am.count_y) + yy;
    am.move(n_x, n_y);
    this.arangeLayers();
  },
  center_relative: function(xx, yy){
    var mm = maps[actual];
    var item = selected_item.element;
    var n_x = (item['pin_x'] * mm.count_x * 100) - 300;
    var n_y = (item['pin_y'] * mm.count_y * 100) - 350;
    //var n_x = (xx * mm.count_x) + 300;
    //var n_y = (yy * mm.count_y) + 350;
    mm.move(-n_x, -n_y);
    this.arangeLayers();
  },
  arangeLayers: function(){
    for(var x = 0; x < 3; x++) maps[x].setVisible(x == actual);
    maps[actual].fillVisible();
    this.update_pine();
  },
  centerTo: function(blocks){
    var xx = 0;
    var yy = 0;
    for(var x in blocks){
      xx += blocks[x][0];
      yy += blocks[x][1];
    }
    xx /= blocks.length
    yy /= blocks.length
    actual = blocks.length > 2 ? 1 : 2;
    var am = maps[actual];
    am.move(-100*yy*am.count_y/7, -100*xx*am.count_x/6);
    this.arangeLayers();
  },
  set_mode: function(mode){
    if(this.mode) $('#'+this.mode+'_icon').attr({src: this.mode+'.png'});
    $('#'+mode+'_icon').attr({src: mode+'_over.png'});
    this.mode = mode;
    var cursor;
    if(mode === 'zoomin') cursor = 'url(zoomin.cur), default';
    if(mode === 'zoomout') cursor = 'url(zoomout.cur), default';
    if(mode === 'move') cursor = 'move';
    if(mode === 'pine') cursor = 'default';
    $('.virtualMap').css({cursor: cursor});
  },
  update_pine: function(){
    if(selected_item && selected_item.element['pin_x']) {
      var item = selected_item.element;
      var am = maps[actual];
      var x = (item['pin_x'] * am.count_x * 100) - 25 + am.x;
      var y = (item['pin_y'] * am.count_y * 100) - 36 + am.y;
      if( x < -15 || x > 585 || y < -25 || y > 676){
        $('#pine').hide();
      }else{
        $('#pine').css({left: x, top: y}); 
        $('#pine').show(); 
      }
    }else{
      $('#pine').hide();
    }
  }
});

MapLayer = $.klass({
  initialize: function(opts) {
    this.count_x = opts.x;
    this.count_y = opts.y;
    this.limit_x = -opts.x * 100 + 600;
    this.limit_y = -opts.y * 100 + 700;
    this.dir = opts.dir
    this.div = opts.div;
    this.x = 0;
    this.y = 0;
    this.index = opts.index;
    this.div.addClass('virtualMap')
    .attr({id: 'map_' + opts.dir});

    this.blocks = [];
    for(var x = -1; x < opts.y + 1; x++){
       this.blocks[x] = [];
    }
    this.count = 0;
  },
  onmousedown: function(e) {
    e.preventDefault();
    switch(map.mode){
      case 'move':
        this.saveLastPosition(e);
        this.map_move = true;
        break;
      case 'zoomin':
        map.zoom(e.pageX,e.pageY, 1)
        break;
      case 'zoomout':
        map.zoom(e.pageX,e.pageY, 0)
        break;
      case 'pine':
        var selected = $('.selected');
        if(selected.length > 0) {
          var item = selected[0].item.element;
          var cx = maps[actual].count_x
          var cy = maps[actual].count_y
          item['pin_x']= (this.x - e.pageX) / (-100 * maps[actual].count_x);
          item['pin_y']= (this.y - e.pageY) / (-100 * maps[actual].count_y);
          map.update_pine();
        }
        break;
    }
  },
  onmousemove: function(e) {
    if(this.map_move){
      var x = this.x + e.pageX - this.last_x;
      var y = this.y + e.pageY - this.last_y;
      this.move(x, y);
      this.fillMissing(e.pageX - this.last_x, e.pageY - this.last_y);
      this.saveLastPosition(e);
      map.update_pine();
    }
  },
  saveLastPosition: function(e) {
    this.last_x = e.pageX;
    this.last_y = e.pageY;
  },
  fillVisible: function() {
    var y = Math.round(-this.x / 100) - 1; 
    var x = Math.round(-this.y / 100) - 1; 
    for(var xx = x; xx < 9 + x; xx++)
      for(var yy = y; yy < 8 + y; yy++){
        if(this.blocks[xx] && this.blocks[xx][yy] == null){
          this.insertBlock(xx,yy);
        }
      }
  },
  fillMissing: function(xx, yy) {
    if(xx > 50 || yy > 50 || ++this.count > 10){
      this.fillVisible();
      this.count = 0;
      return;
    }
    var y = Math.round(-this.x / 100); 
    var x = Math.round(-this.y / 100); 
    var fy = xx > 0 ? y - 1 : y + 6;
    var fx = yy > 0 ? x - 1 : x + 7;
    for(var z = x - 1; z < 9 + x; z++)
        if(this.blocks[z] && this.blocks[z][fy] == null){
          this.insertBlock(z,fy);
        }
    for(var z = y - 1; z < 9 + y; z++)
        if(this.blocks[fx] && this.blocks[fx][z] == null){
          this.insertBlock(fx,z); //dont insert blocks outside map!
        }
  },
  insertBlock: function(x, y){
    var block = document.createElement('div');
    var img = new Image();
    $(img).attr({src: this.dir+'/'+x+'_'+y+'.gif', unselectable: 'on'});
    $(block).addClass('mapBlock')
      .attr({id: this.dir+'_'+x+'_'+y, unselectable: 'on'})
      .css({top: x * 100, left: y * 100})
      .append(img);
    this.div.append(block);
    this.blocks[x][y] = block;
  },
  move: function(x,y){
    this.x = x > 0 ? 0 : x < this.limit_x ? this.limit_x : x;
    this.y = y > 0 ? 0 : y < this.limit_y ? this.limit_y : y;
    this.div.css({left: this.x, top: this.y});
  },
  setVisible: function(visible){
    var index = visible ? 1 : 0;
    this.div.css({'z-index': index });
  }
});


Item = $.klass({
  initialize: function(opts, index) {
    this.text = opts.name;
    this.clean_name = opts.clean_name;
    this.blocks = opts.blocks;
    this.hidden = false;
    this.index = index;
    this.element = opts;
    var dd = document.createElement('div');
    this.div = $(dd);
    this.div.append(this.text).
    addClass('listElement').
    mousedown(this.onmousedown);
    dd.item = this;
    $('#streets_list').append(this.div);
  },
  hide: function(){ if(!this.hidden){ this.div.hide(); this.hidden = true;}},
  show: function(){ if(this.hidden){ this.div.show(); this.hidden = false;}},
  test: function(regexp){
    regexp.exec(this.clean_name) || regexp.exec(this.text) ? this.show() : this.hide();
  },
  onmousedown: function(){
    obj = $(this);
    if(selected) selected.removeClass('selected');
    obj.addClass('selected');
    selected = obj;
    selected_item = this.item;
    this.item.center();
  },
  center: function(){
    if(this.element.pin_x && this.element.pin_y) {
      actual = 2;
      map.center_relative(this.element.pin_x, this.element.pin_y);
    }else{
      map.centerTo(this.blocks);
    }
  }
});
