Ext.namespace('Ext.ux.panel');

Ext.ux.GMapPanel = Ext.extend(Ext.Panel, {
  /**
     * @cfg {Boolean} border
     * Defaults to <tt>false</tt>.  See {@link Ext.Panel}.<code>{@link Ext.Panel#border border}</code>.
     */
  border: false,

  /**
     * @cfg {Array} respErrors
     * An array of msg/code pairs.
     */
  respErrors: [{
    code: 'UNKNOWN_ERROR',
    msg: 'A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.'
  },{
    code: 'ERROR',
    msg: 'There was a problem contacting the Google servers.'
  },{
    code: 'ZERO_RESULTS',
    msg: 'The request did not encounter any errors but returns zero results.'
  },{
    code: 'INVALID_REQUEST',
    msg: 'This request was invalid.'
  },{
    code: 'REQUEST_DENIED',
    msg: 'The webpage is not allowed to use the geocoder for some reason.'
  },{
    code: 'OVER_QUERY_LIMIT',
    msg: 'The webpage has gone over the requests limit in too short a period of time.'
  }],
  /**
     * @cfg {String} respErrorTitle
     * Defaults to <tt>'Error'</tt>.
     */
  respErrorTitle : 'Error',
  /**
     * @cfg {String} geoErrorMsgUnable
     * Defaults to <tt>'Unable to Locate the Address you provided'</tt>.
     */
  geoErrorMsgUnable : 'Unable to Locate the Address you provided',
  /**
     * @cfg {String} geoErrorTitle
     * Defaults to <tt>'Address Location Error'</tt>.
     */
  geoErrorTitle : 'Address Location Error',
  /**
     * @cfg {String} geoErrorMsgAccuracy
     * Defaults to <tt>'The address provided has a low accuracy.<br><br>Level {0} Accuracy (8 = Exact Match, 1 = Vague Match)'</tt>.
     */
  geoErrorMsgAccuracy : 'The address provided has a low accuracy.<br><br>Level {0} Accuracy (8 = Exact Match, 1 = Vague Match)',
  gmapType : 'map',
  /**
     * @cfg {Object} setCenter
     * The initial center location of the map. The map needs to be centered before it can be used.
     * A marker is not required to be specified.
     * More markers can be added to the map using the <code>{@link #markers}</code> array.
     * For example:
     * <pre><code>
setCenter: {
    geoCodeAddr: '4 Yawkey Way, Boston, MA, 02215-3409, USA',
    marker: {title: 'Fenway Park'}
},

// or just specify lat/long
setCenter: {
    lat: 42.345573,
    lng: -71.098326
}
     * </code></pre>
     */
  /**
     * @cfg {Number} zoomLevel
     * The zoom level to initialize the map at, generally between 1 (whole planet) and 40 (street).
     * Also used as the zoom level for panoramas, zero specifies no zoom at all.
     * Defaults to <tt>3</tt>.
     */
  zoom: 11,
  /**
     * @cfg {Number} yaw
     * The Yaw, or rotational direction of the users perspective in degrees. Only applies to panoramas.
     * Defaults to <tt>180</tt>.
     */
  yaw: 180,
  /**
     * @cfg {Number} pitch
     * The pitch, or vertical direction of the users perspective in degrees.
     * Defaults to <tt>0</tt> (straight ahead). Valid values are between +90 (straight up) and -90 (straight down).
     */
  pitch: 0,
  /**
     * @cfg {Boolean} displayGeoErrors
     * True to display geocoding errors to the end user via a message box.
     * Defaults to <tt>false</tt>.
     */
  displayGeoErrors: false,
  /**
     * @cfg {Boolean} minGeoAccuracy
     * The level (between 1 & 8) to display an accuracy error below. Defaults to <tt>7</tt>. For additional information
     * see <a href="http://code.google.com/apis/maps/documentation/reference.html#GGeoAddressAccuracy">here</a>.
     */
  minGeoAccuracy: 7,
  // private
  mapDefined: false,
  // private
  mapDefinedGMap: false,
  // private
  initComponent : function(){

    this.addEvents(
      /**
             * @event mapready
             * Fires when the map is ready for interaction
             * @param {GMapPanel} this
             * @param {GMap} map
             */
      'mapready'
      );
    Ext.ux.GMapPanel.superclass.initComponent.call(this);


  },
  // private
  afterRender : function(){

    var wh = this.ownerCt.getSize();
    Ext.applyIf(this, wh);

    Ext.ux.GMapPanel.superclass.afterRender.call(this);
    if (this.gmapType === 'map'){
      this.gmap = new google.maps.Map(this.body.dom, {
        zoom:this.zoom,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      });
      this.mapDefined = true;
      this.mapDefinedGMap = true;
    }

    if (!this.mapDefined && this.gmapType){
      this.gmap = new google.maps.Map(this.body.dom, {
        zoom:this.zoom,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      });
      //this.gmap.setMapType(this.gmapType);
      this.mapDefined = true;
      this.mapDefinedGMap = true;
    }

    google.maps.event.addListener(this.getMap(), 'tilesloaded', this.onMapReady);

    if (typeof this.setCenter === 'object') {
      if (this.gmapType === 'map'){
        var point = new google.maps.LatLng(this.setCenter.lat,this.setCenter.lng);
        this.getMap().setCenter(point);
      }
    }

    if (typeof this.bounds === 'object') {
      if (this.gmapType === 'map'){
        this.getMap().fitBounds(this.bounds);
      }
    }

    if (Ext.isArray(this.setRoute)) {
      if (this.gmapType === 'map'){
        var route = route1 = new google.maps.Polyline(
        {
          path: this.setRoute,
          strokeColor: "#0000FF",
          strokeOpacity: 0.5,
          strokeWeight: 4
        });
        route.setMap(this.getMap());
      }
    }

    if(this.startIcon)
    {
      var starticon = 'images/cyclingfeedarea.png';
      var startmarker = new google.maps.Marker(
      {
        position: this.setRoute[0],
        map: this.getMap(),
        title:"Start og depot",
        icon: starticon
      });
    }

    if(this.finishIcon)
    {
      var finishicon = 'images/racing.png';
      var finishmarker = new google.maps.Marker(
      {
        position: this.setRoute[this.setRoute.length-1],
        map: this.getMap(),
        title:"Mål og tidtagning",
        icon: finishicon
      });
    }

  },
  // private
  onMapReady : function(){

    var mapdiv= this.getDiv();
    var compdiv = Ext.get(mapdiv)
    var newcomp=compdiv.parent().parent();
    var comp=Ext.getCmp(newcomp.id);
    comp.fireEvent('mapready', comp, comp.getMap());

  },
  // private
  onResize : function(w, h){

    Ext.ux.GMapPanel.superclass.onResize.call(this, w, h);

    // check for the existance of the google map in case the onResize fires too early
    if (typeof this.getMap() == 'object') {
      google.maps.event.trigger(this.getMap(), 'resize');
    }

  },
  // private
  setSize : function(width, height, animate){

    Ext.ux.GMapPanel.superclass.setSize.call(this, width, height, animate);

    // check for the existance of the google map in case setSize is called too early
    if (typeof this.getMap() == 'object') {
      google.maps.event.trigger(this.getMap(), 'resize');
    }

  },
  /**
     * Returns the current google map which can be used to call Google Maps API specific handlers.
     * @return {GMap} this
     */
  getMap : function(){

    return this.gmap;

  },
  /**
     * Returns the maps center as a GLatLng object
     * @return {GLatLng} this
     */
  getCenter : function(){

    return this.getMap().getCenter();

  },
  /**
     * Returns the maps center as a GLatLng object
     * @return {GLatLng} this
     */
  setCenter : function(latlng){

    this.getMap().setCenter(latlng);

  },
  // private
  geoErrorMsg : function(title,msg){
    if (this.displayGeoErrors) {
      Ext.MessageBox.alert(title,msg);
    }
  },
  // private
  respErrorMsg : function(code){
    Ext.each(this.respErrors, function(obj){
      if (code == obj.code){
        Ext.MessageBox.alert(this.respErrorTitle, obj.msg);
      }
    }, this);
  }
});

Ext.reg('gmappanel',Ext.ux.GMapPanel);
