Ajax.Responders.register({
  onCreate: function() {
  if (Ajax.activeRequestCount === 1) {
    Element.show("loading");
    }
  },
  onComplete: function() {
    if (Ajax.activeRequestCount === 0) {
      Element.hide("loading");
      }
    }
});


function initMap(options){
  var followUp = null;
  for(var option in options){self[option] = options[option];}
  var mapOptions = {numZoomLevels: 18}
  map = new OpenLayers.Map($('map'),mapOptions);
  if(name == 'India - Yahoo'){ 
    baseLayer = new OpenLayers.Layer.Yahoo("Yahoo",
        {sphericalMercator: true, maxExtent: new OpenLayers.Bounds(-20037508, -20037508,20037508, 20037508.34)}
        );
  }
  map.addLayer(baseLayer);
  trgProj = baseLayer.projection;
  map.setCenter(new OpenLayers.LonLat(lon,lat).transform(srcProj,trgProj),zoom);
  state = "UNKNOWN";

  /**
   *case statements here should be replaced by lookup references
   */

  var template = {externalGraphic: "${icon}",graphicWidth:"${width}",graphicHeight:"${height}"};
  
  var cont = {
        radius: function(feature){return Math.min(feature.attributes.count, 7) + 3;},
        icon: function(feature){
           _level = Math.min(feature.attributes.count,4) - 1;
           if(isNaN(_level)){
              if(feature.attributes.icon){
                return "/images/" + feature.attributes.icon;
              }else{
                return "/images/marker.png"; 
              }
           }
           if(_level == 0 &&  feature.attributes.icon){
             return "/images/" + feature.attributes.icon;
           }else{
             return "/images/cluster"+_level+".png";
           }
         },

        width: function(feature){ _level = Math.min(feature.attributes.count,4) - 1; 
          w = 32;
          switch(_level){
            case 0:
             w = 32;
              break;
            case 1:
             w =  44;
              break;
            case 2:
             w =  53;
              break;
            case 3:
             w = 76;
              break;
          }
          return w;
        },
        height:function(feature){
          _level = Math.min(feature.attributes.count,4) - 1;
          h = 29;
          switch(_level){
            case 0:
              h = 29;
              break;
            case 1:
              h = 36;
              break;
            case 2:
              h = 48;
              break;
            case 3:
              h = 60;
              break;
          }
          return h;
        }
      };
  var style = new OpenLayers.Style(template, {context: cont});
  vLayer = new OpenLayers.Layer.Vector("Mapposts",
      {
       projection: new OpenLayers.Projection("EPSG:4326"),
       styleMap: new OpenLayers.StyleMap({
         "default": style,
         "select": g
        }),
         strategies: [cluster],
         eventListeners : {"beforefeatureadded": cacheFeature}
       });

  cluster.activate();
  sLayer = new OpenLayers.Layer.Vector("Selection",{
                  'styleMap' : new OpenLayers.StyleMap({"default": g}),
                  'projection': new OpenLayers.Projection("EPSG:4326")
  });
  map.addLayer(sLayer);
  map.addLayer(vLayer);
  for(var key in controls){
    var control = controls[key];
    map.addControl(control);
    control.activate();
  }
  selectCtl = new OpenLayers.Control.SelectFeature(vLayer,{toggle:true,clickout:true,multiple:false,hover:false,onSelect:getInfo,onUnselect:closeInfo});
  map.addControl(selectCtl);
  selectCtl.activate();
  dragControl = new OpenLayers.Control.DragFeature(vLayer,{onComplete:updateLocations});
  map.addControl(dragControl);
  request(self.followUp);

  new Draggable("info");
}

function cacheFeature(event){
  feature = event.feature;
  if(state == OpenLayers.State.INSERT){
    newFids.push(feature.attributes.fid || feature.fid);
  }
}

function cancelEdit(){
  newFeatures = [];
  newFids.each(
      function(_fid){
        feature = vLayer.features.detect(function(e){return e.attributes.fid == _fid || e.fid == _fid});
        if(feature){newFeatures.push(feature);}
      }
  );
  vLayer.destroyFeatures(newFeatures);
  newFids = [];
}

function hide_user_msg() {
  setTimeout("Element.hide('user_message')",10000);
}


function updateSubdomain(input_obj) {
  var value = input_obj.value.toLowerCase().gsub(/[!@#$%^&*()\s]+/, "-");
  $('subcommunity').innerHTML = 'http://' + value + '.mapunity.org';
  $('url').value = value;
}


function get(url){
  request(url);
}

function upd(url,target){
  new Ajax.Updater(target, url, {method: 'get',asynchronous:true, evalScripts:true});
}

function u(url){
  new Ajax.Request(url,{method: 'get',evalScripts:true, onSuccess: function(transport){
      $('info').innerHTML = transport.responseText;
      transport.responseText.evalScripts();
      transport.responseText.extractScripts();
      Element.show('info');
      }

    });
}


function request(url){
  if(!url){return;}
  new Ajax.Request(url, {method: 'get',asynchronous:true, evalScripts:true,onSuccess:function(transport){transport.responseText.evalScripts();}});
}

function getInfo(feature){
  var geom = feature.geometry;
  map.setCenter(geom.getBounds().getCenterLonLat());
  if(feature.attributes.count > 1){
    var clusterBounds = new OpenLayers.Bounds();
    clstr = feature.cluster;
    clstr.each(function(e){clusterBounds.extend(e.geometry.getBounds())});
    map.setCenter(clusterBounds.getCenterLonLat(),map.getZoomForExtent(clusterBounds));
    return;
  }
  if(feature.attributes.info){
    showInfo(feature);
    return;
  }
  map.zoomTo(parseInt(feature.attributes.zoom));
  request("/info/"+feature.attributes.fid);
}

function showInfo(feature){
    html = "<div style='border:5px solid #fbef65;'>"
      + "<span style='position:absolute;top:0px;right:0px;'><img src=/images/close.gif onClick='closeInfo();' /></span>"
      + "<div style='float:left;padding:15px 4px 4px 10px;display:inline;'><img src='/images/marker.png'/></div>"
      + "<div style='float:left;padding:15px 4px 4px 4px;display:inline;width:300px;'> <span class=post_title>"
      + feature.attributes.info.split(",")[0]
      + "</span></br>"
      + "</div>"
      + "<div style='clear:both;'> <ul id=tabnav>  <li> <a href=# class=current>Details</a></li> </ul></div>"
      + "<div style='padding:4px 4px 2px 10px;'>" + feature.attributes.info.gsub(",","</br>") + "</div>"
      + "<div id=inftr style='clear:both;padding:8px 8px 8px 10px;background:#f6f4f7;border-top:2px solid #dcdcdc;'></div>"
      + "</div>";
      $("info").update(html);
      Element.show("info");
}

function closeInfo(){
  Element.hide("info");
  selectCtl.unselectAll();
  sLayer.destroyFeatures();
  if (state != OpenLayers.State.INSERT){return;}
  cancelEdit();
}

function updateLocations(feature,pixel){
  loc = map.getLonLatFromViewPortPx(pixel);
  loc.transform(trgProj,srcProj);

  if($('record_' + frm)) {
    $('record_' + frm).lat.value = loc.lat;
    $('record_' + frm).lon.value = loc.lon;
    $('record_' + frm).z.value = map.getZoom();
  }
  else{
    children = $('disp').childNodes;
    for(var i=0;children.length;i++) {
      if(children[i].nodeName == "FORM") {
        children[i].lat.value = loc.lat;;
        children[i].lon.value = loc.lon;
        children[i].z.value = map.getZoom();
        break;
      }
    }
  }
}

function render(result,options){
  var mapBounds = map.getExtent();
  cache = result;
  closeInfo();
  vLayer.destroyFeatures();
  var pointList = [];
  disableEdit();
  var center = (typeof(options) == 'undefined' || options.center) ? true : false;
  /**
   * this rule should be applied for a newly added feature or feature being editted
   *
   */
  var point = null;
  var disp = "";
  var _bounds = new OpenLayers.Bounds();
  var pgeom = null;
  result.each(
      function(record){
        rec_layer = record.layer ? record.layer.strip() : null;
        if(!(hiddenLayers.include(rec_layer))){
          _props = {'fid': record.id,'info': record.info,'icon': record.icon,'clickoutTolerance':2, 'zoom': record.zoom || 10};
          pgeom = new OpenLayers.Geometry.Point(record.lon,record.lat);
          pgeom.transform(srcProj,trgProj);
          _bounds.extend(pgeom.getBounds());
          point = new OpenLayers.Feature.Vector(pgeom,_props, null);
          point.fid = record.id;
          point.icon = record.icon;
          pointList.push(point);
          disp += "<li id=" + "e_" + point.attributes.fid +"  class=brief>" + record.desc + "</li>";
        }
      }
  );

  vLayer.addFeatures(pointList);
  Element.update(dest,"");
  new Insertion.Bottom(dest,rsltHTML);
  new Insertion.Bottom(rslt,disp);
  attachEvents();
  
  _bounds = resizeExtent(_bounds);
  if(!center){
    _bounds = mapBounds;
  }
  var _center = _bounds.getCenterLonLat();
  _center.lon = _center.lon * 0.80;
  if (center == true){
    map.setCenter(_center);
  }
  map.zoomTo(map.getZoomForExtent(_bounds));
}

function attachEvents(){
  var cl = $(rslt).childElements();
  cl.each(
      function(el){
        var _fid = el.id.split("_").last();
        var attribs = {fid: _fid};
        Event.observe(el,"click",ftSelect.bindAsEventListener(el,attribs));
      }
  );
}


function ftSelect(evt){
  var _data = $A(arguments).last();
  var _fid = _data.fid || 0;
  var ftSelected = null;
  Try.these(
    function(){ return ftSelected = cluster.features.detect(function(f){return f.attributes.fid == _fid;});},
    function(){ return ftSelected = vLayer.features.detect(function(f){return f.attributes.fid == _fid;});}
  );
  if(ftSelected){
    fg = ftSelected.geometry;
    sLayer.addFeatures(ftSelected);
    getInfo(ftSelected);
  }
}
  
function invokeForm(ll){
    if (state != 'Insert') return;
    var point = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(ll.lon,ll.lat),null,g);
    point.fid = parseInt(- Math.random(1000) * 1000);
    point.editable = true;
    vLayer.addFeatures(point);
    z = map.getZoom();
    loc =  ll.transform(trgProj,srcProj);
    request('/record/forms/');
}



function addNew(idx){
  request('/record/new/'+ idx + '?lat=' + loc.lat + '&lon=' + loc.lon + '&z=' + z);
}



function markLatLon() {
    y = $('search_lat').value;
    x = $('search_lon').value;
    enableEdit();
    loc = new OpenLayers.LonLat(x,y);
    loc.transform(srcProj,trgProj);
    map.setCenter(loc);
    invokeForm(loc);
}

function activateFeatureEdit(fid){
  feature = vLayer.features.detect(function(e){return e.attributes.fid == fid;});
  feature.editable = true;

}

function enableEdit(){
  dragControl.activate();
  if(cluster.layer){cluster.deactivate();}
}

function disableEdit(){
  state = "UNKNOWN";
  dragControl.deactivate();
  if(cluster.layer){cluster.activate();}
}

function resizeExtent(bounds){
  bounds.left *= 0.80;
  bounds.bottom *= 0.80;
  bounds.right *= 1.20;
  bounds.top *= 1.20;
  return bounds;
}


/**
 * click control handler
 */
OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control,{
    defaultHandlerOptions: {
      'single': true,
      'double': true,
      'pixelTolerance':0,
      'stopSingle':false,
      'stopDouble':false
    },
    initialize: function(options){
        this.handlerOptions = new OpenLayers.Util.extend({},this.defaultHandlerOptions);
        OpenLayers.Control.prototype.initialize.apply(this,arguments);
        this.handler = new OpenLayers.Handler.Click(this,{
          'click': this.onClick,
          'dblclick': this.onDblClick
          },this.handlerOptions);
    },
    onClick: function(evt){
      if (state == OpenLayers.State.INSERT){
        enableEdit();
        loc = map.getLonLatFromViewPortPx(evt.xy);
        invokeForm(loc);
      }
    },
    onDblClick: function(evt){
      //do nothing
    }
});

var controls = {
  "logo": new OpenLayers.Control.MapunityText(),
  "position": new OpenLayers.Control.MousePosition({'displayProjection': new OpenLayers.Projection("EPSG:4326"),'numDigits':4}),
  "click": new OpenLayers.Control.Click({handlerOptions:{'double':true,'single':true,'stopSingle':true,'stopDouble':true}}),
  "panZoom": new OpenLayers.Control.PanZoomBar()
}

var g = OpenLayers.Util.extend({},OpenLayers.Feature.Vector.style['default']);
g.graphicWidth = 45;
g.graphicHeight = 45;
g.graphicXOffset = -(g.graphicWidth/2);
g.graphicYOffset = -(g.graphicHeight/2);
g.externalGraphic = "../images/highlight.gif";
g.graphicOpacity = 1;
  
var name = 'India - Mapunity';
var cluster = new OpenLayers.Strategy.Cluster();
var tile_url = ["http://tiles0.mapunity.org","http://tiles1.mapunity.org","http://tiles2.mapunity.org","http://tiles3.mapunity.org"];
var baseLayer = new OpenLayers.Layer.GTileGrid(name,tile_url,{},{'projection': new OpenLayers.Projection("EPSG:4326")});
var map = null;
var zoom = 5;
var z = zoom;
var lat = 23.62;
var lon = 81.7;
var minZoom = 10;
var maxZoom = 17;
var vLayer = null; //vector layer
var sLayer = null; // for displaying selection
var state = "UNKNOWN"; //initialize the state to unknown
var dragControl = null;
var loc = null;
var newFids = [];
var selectedFeature = null;
var frm = null;
var cache = null;
var hiddenLayers = [];
var dest = "posts";
var rslt = "results";
var rsltHTML = "<ul id=results></ul>";
var trgProj = new OpenLayers.Projection("EPSG:900913");
var srcProj = new OpenLayers.Projection("EPSG:4326");
