var map;
// Start position for the map (hardcoded here for simplicity,
// but maybe you want to get from URL params)
var lat = 45.53;
var lon = -122.67;
var zoom = 11;
MapUtils = {
  selected_address_field: null,
  mapPanel: null,
  initMap: function () {
    Ext.QuickTips.init();
    OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {
      defaultHandlerOptions: {
        'single': true,
        'double': false,
        'pixelTolerance': 0,
        'stopSingle': false,
        'stopDouble': false
      },
      initialize: function (options) {
        this.handlerOptions = OpenLayers.Util.extend({},
        this.defaultHandlerOptions);
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
        this.handler = new OpenLayers.Handler.Click(this, {
          'click': this.trigger
        },
        this.handlerOptions);
      },
      trigger: function (e) {
        var lonlat = map.getLonLatFromViewPortPx(e.xy);
        lonlat.transform(map.getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));
        if (MapUtils.selected_address_field) {
          MapUtils.selected_address_field.setValue(Math.round(lonlat.lat * 10000) / 10000 + "," + Math.round(lonlat.lon * 10000) / 10000);
          MapUtils.selected_address_field = null;
        }
      }
    });

    map = new OpenLayers.Map({
      controls: [
       new OpenLayers.Control.Navigation(),
       new OpenLayers.Control.PanZoomBar(),
       new OpenLayers.Control.MousePosition(),
       new OpenLayers.Control.DragPan()
      //new OpenLayers.Control.Attribution()
      ],
      maxExtent: new OpenLayers.Bounds(-13730842.907054, 5615443.61173668, -13545736.3174682, 5750616.08844726),
      restrictedExtent: new OpenLayers.Bounds(-13730842.907054, 5615443.61173668, -13545736.3174682, 5750616.08844726),
      maxResolution: 153,
      numZoomLevels: 19,
      units: 'm',
      projection: new OpenLayers.Projection("EPSG:900913"),
      displayProjection: new OpenLayers.Projection("EPSG:4326")
    });
    var click = new OpenLayers.Control.Click();
    map.addControl(click);
    click.activate();
    var routeStyle = new OpenLayers.StyleMap({
      'strokeWidth': 5,
      'strokeColor': '#ffff00'
    })

    mapnik = new OpenLayers.Layer.OSM.Mapnik("Open Street Map (mapnik)");
//    var osm = new OpenLayers.Layer.WMS("OpenStreetMap", 
//        "http://maps.opengeo.org/geowebcache/service/wms", {
//          layers: "openstreetmap",
//          format: 'image/png',
//          bgcolor: '#A1BDC4',
//        },
//        {
//          sphericalMercator: true,
//          wrapDateLine: true
//        }
//    );
    
    google = new OpenLayers.Layer.Google("Google Physical", {
      type: G_PHYSICAL_MAP,
      sphericalMercator: true
    })
    google_st = new OpenLayers.Layer.Google("Google Street", {
      type: G_NORMAL_MAP,
      sphericalMercator: true
    })
    bike_routes = new OpenLayers.Layer.WMS("Bike Routes", "http://bikemap.garnix.org/cgi-bin/mapserv?", {
      layers: "bike_rte",
      transparent: true
    },
    {
      isBaseLayer: false,
      visibility: false
    });

    var route;
    var display_layers = [mapnik, google_st, google, bike_routes]

    var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
 
    MapUtils.mapPanel = new GeoExt.MapPanel({
      map: map,
      border: false,
      region: 'center',
      layers: display_layers,
      layout: 'fit',
      id: 'olMap'
    });
    Ext.getCmp('center-panel').add(MapUtils.mapPanel);
    vp.addListener('resize', function(e){MapUtils.resizeMapPanel()});
    MapUtils.resizeMapPanel();
    map.setCenter(new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()), 12);
    MapUtils.addLayerWindow();
    MapUtils.addFormPanel();
    MapUtils.addRoute(route_id);
    MapUtils.showBetaWarning();
  },
  showBetaWarning: function() {
    if(!Ext.state.Manager.get('sawWarning')) {
       Ext.Msg.show({msg: 'This site is currently in beta, please report any problems (after reading the FAQ).',
                     buttons: Ext.Msg.OK,
                     icon: Ext.MessageBox.WARNING});
      Ext.state.Manager.set('sawWarning', true);
    }
  },
  resizeMapPanel: function(){
    Ext.getCmp('center-panel').setHeight(vp.getHeight()-Ext.getCmp('header-panel').getHeight());
    vp.doLayout();
  },
  addFormPanel: function(){
    formPanel = new GeoExt.form.FormPanel({
      border: false,
      buttonAlign: 'left',
      id: 'searchformpanel',
      monitorResize: true,
      items: [
        {
         xtype: "textfield",
          id: "start_address",
          name: "start_address",
          allowBlank: !Ext.isIE,
          emptyText: start_address,
          fieldLabel: "<b>Start Address</b>",
          anchor: '0',
          listeners: {'focus': function (e) {MapUtils.selected_address_field = e}}
        },
        {
          xtype: "textfield",
          anchor: '0',
          id: "finish_address",
          name: "finish_address",
          allowBlank: !Ext.isIE,
          emptyText: finish_address,
          fieldLabel: "<b>Finish Address</b>",
          listeners: {'focus': function (e) {MapUtils.selected_address_field = e}}
        }
      ],
      keys: [{
        key: Ext.EventObject.ENTER,
        fn: function () {MapUtils.findRoute(formPanel.getForm().getValues())}
      }],
      bbar: new Ext.ux.StatusBar({
               id: 'basic-statusbar',
               // defaults to use when the status is cleared:
               defaultText: 'Ready',
               defaultIconCls: 'x-status-valid',
               // values to set initially:
               text: 'Ready',
               border: true,
               iconCls: 'x-status-valid',
               statusAlign: 'right',
               // any standard Toolbar items:
               items: [{
                        id: 'route_button',
                        text: "Find me a Bike Route",
                        handler: function () {
                          if (!Ext.isIE) {
                            notice = Ext.DomQuery.selectNode('div[id=notice]');
                            notice.style.visibility = 'hidden';
                            notice.className = '';
                          }
                          MapUtils.findRoute(formPanel.getForm().getValues())
                        }
                      },
                      '-',
                      {text: 'Advanced Options(coming soon)'},
                      '-'
                      ]
             })
      
    });
    formPanel.render("formpanel");
    if (!Ext.isIE) {
      formtips = {
        text: "<b>Don't know the address?</b><br>Click in the address field, then click on the map to add a point",
        width: 300,
        dismissDelay: 3000,
        trackMouse: false,
        showDelay: 5000
      };
      formtips.target = 'finish_address';
      Ext.QuickTips.register(formtips);
      formtips.target = 'start_address';
      Ext.QuickTips.register(formtips);
    }
  },
  addLayerWindow: function() {
    var baseLayerList = new GeoExt.tree.LayerContainer({
      text: 'Base Map',
      layerStore: MapUtils.mapPanel.layers,
      leaf: false,
      flex: 1,
      expanded: true,
      rootVisible: false
    });
    var layerTree = new Ext.tree.TreePanel({
      root: baseLayerList
    });

    var legendPanel = new GeoExt.LegendImage({
      id: 'legend',
      text: 'Legend',
      labelCls: 'legend',
      //bodyStyle: 'padding:5px',
      autoScroll: true,
      hidden: false,
      collapsible: true,
      flex: 1,
      border: true,
      url: '/cgi-bin/mapserv?LAYER=bike_rte&TRANSPARENT=true&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetLegendGraphic&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&FORMAT=image%2Fpng'
    });

    var layerWindow = new Ext.Window({
      id: "layerwindow",
      title: "Layers",
      x: 60,
      y: 130,
      height: 233,
      width: 210,
      layout: "vbox",
      layoutConfig: {
          align : 'stretch',
          pack  : 'start'
        },
      closable: false,
      minimizable: false,
      items: [layerTree, legendPanel]
    }).show();
   
  },
  addRoute: function (route_id) {
    if (route_id && route_id != '') {
      var layerName = "<b>Your Route</b>";
      var routeStyle = new OpenLayers.StyleMap({
        'strokeWidth': 5,
        'strokeColor': '#ff0000'
      })
      map.getLayersByName(layerName).each(function (l) {
        map.removeLayer(l)
      })
      route_gml = new OpenLayers.Layer.GML(layerName, "/routes/" + route_id + "/geometries.gml", {
        typename: "routes",
        name: "Current Route",
        featureClass: OpenLayers.Feature.GML,
        styleMap: routeStyle,
        //displayInLayerSwitcher: false,
        projection: new OpenLayers.Projection("EPSG:4326")
      });
      MapUtils.insertPermalink(route_id);
      //console.log(route_gml);
      route_gml.events.register("loadend", route_gml, function () {
        map.zoomToExtent(route_gml.getDataExtent())
      });
      map.addLayer(route_gml);
      map.raiseLayer(map.getLayersByName(layerName).first(), -1);
      Ext.getCmp('layerwindow').setHeight(Ext.getCmp('layerwindow').getHeight() + 16)
    }
  },
  displaySBError: function(err, doClear) {
    sb=Ext.getCmp('basic-statusbar');
    err=err.split('<br>').first().trim();
    sb.setStatus({
      text: err,
      iconCls: 'x-status-error',
      clear: doClear // auto-clear after a set interval
    });
  },   
  findRoute: function (p) {
    sb=Ext.getCmp('basic-statusbar');
    if (p.finish_address=='' || p.start_address=='') {
      MapUtils.displaySBError('Please enter both addresses!', true);
      return null;
    }
    sb.showBusy();
    var protocol = new OpenLayers.Protocol.HTTP({   url: "/routes/create",
         format: new OpenLayers.Format.GeoJSON(),
      params: p
    });
    protocol.read({   callback: function (response) {       
        if (response.success()) {
          if (!response.features) {
            console.log(response);
            x = new OpenLayers.Format.JSON()
            y = Ext.util.JSON.decode(response.priv.responseText);
            MapUtils.displaySBError(y.error);
          } else {           features = response.features;
            //console.log(features[0].attributes);
            if (features[0].attributes.finish_address) {
              Ext.getCmp('finish_address').setValue(features[0].attributes.finish_address)
            };
            if (features[0].attributes.start_address) {
              Ext.getCmp('start_address').setValue(features[0].attributes.start_address)
            };
            sb.clearStatus();       
            //console.log(features);
            MapUtils.addRoute(features[0].fid);
          }       
        } else {
          sb.setStatus({
            text: 'A server error occurred.',
            iconCls: 'x-status-error'
          });
          console.log("failure");       
        }   
      }
    });
  },
  insertPermalink: function(route_id) {
    if (route_id) {
      p=Ext.get('permalink')
      if (p) {
        p.update('<a href="/map/' + route_id + '">Permalink for this Route</a>');
      }
      else {
        sb=Ext.getCmp('basic-statusbar')
        sb.insert(4,'<span id="permalink"><a href="/map/' + route_id + '">Permalink for this Route</a></span>');
        sb.doLayout();
      }
    }
  }
}
