/*
 * Assists in rendering the google map get directions page
 */
(function() {

function getDirections() {
    var notValid = DGPWidgetsCommon.trimLeadingAndTrailingSpaces(jQuery('#dirFromInput'));
    MapDirections.clearErrorMessages();
    if (notValid) {
        MapDirections.showErrorMessage(INVALID_FROM_ADDRESS);
    } else {
        MapDirections.showDirections(jQuery('#dirFromInput').val(),jQuery('#dirToLatLng').val());
        jQuery('#dgpPopup .tntPrintVariant').show();
    }
    return false;
}

MapDirections = {
  GDir : null,
  directionsMap : null,
  locale: null,
  directionMapLoaded:false,

  // For publish event, either apply the default layout name from the session or supply a layout name
  overrideReportingInfo: false,
  displayDirectionsOnPopup: false,

  /*
   * This method can be overridden if the map creation process needs to be customized
   */
  createMap : function() {
    return MapDirections.createGoogleMap();
  },

  createGoogleMap : function() {
    return new GMap2(document.getElementById("directionsMap"));
  },

  /*
   * Bind events to all GetDirection components
   */
  initialize : function(extensionObject) {
    // Bind print page event
    MapDirections.bindPrintEvent();

    // Bind get directions form submit
    MapDirections.bindFormSubmitEvent();

    for (var key in extensionObject) {
      if (!(key in MapDirections)) MapDirections[key] = extensionObject[key];
    }
  },

  /*
   * Binds print event on click of print icon
   */
  bindPrintEvent : function() {
      jQuery("#popupHeader .directionsPrint").livequery('click', function(){
          if (MapDirections.directionMapLoaded) {
              DGPWidgetsCommon.publishView('HoursAndDirections', 'DrivingDirections_locationsHours_results_Print', 'DrivingDirections_results_print');
          }else {
              DGPWidgetsCommon.publishView('HoursAndDirections', 'DrivingDirections_locationHours_Print', 'DrivingDirections_print');
          }
          jQuery.jPrintAreaLslp('#childPopup_ScrollingArea');
          return false;
      });
  },

  /*
   * Binds GetDirections form submit event
   */
  bindFormSubmitEvent : function() {
      jQuery('#directionsForm').livequery('submit',getDirections);
  },

  /*
   * clear and hide the element that holds error messages from loading the map
   */
  clearErrorMessages : function() {
    if (MapDirections.errorMessages)
      jQuery(MapDirections.errorMessages).empty().hide();
  },

  /*
   * Show directions from the input From address and the To address
   */
  showDirections : function(fromAddress, toAddress) {

    // while in edit mode or WIP, fromAddress may not exist; short-circuit this
    if (!liveMode || editMode) {
      if (!fromAddress || (fromAddress.replace(/\s+/g,'') == '')) {
        fromAddress = toAddress;
      }
    }

    MapDirections.GDir = new GDirections(MapDirections.directionsMap,
                       document.getElementById("directionsPanel"));

    // Register load/error event listeners
    GEvent.addListener(MapDirections.GDir, "load", MapDirections.clearOldMarker);
    GEvent.addListener(MapDirections.GDir, "error", MapDirections.handleErrors);
    GEvent.addListener(MapDirections.GDir, "addoverlay", MapDirections.overrideGStyles);
    // Show scrollbar if required
    if(MapDirections.displayDirectionsOnPopup) {
      GEvent.addListener(MapDirections.GDir, "addoverlay", PortalPopup.showHideScrollbar);
    }
    MapDirections.GDir.load("from: " + fromAddress + " to: " + toAddress,
        { "locale": MapDirections.locale });
  },

  /*
   * Clear the old markers and the directions information,
   * if the user enters a valid "from address".
   */
  clearOldMarker : function() {
    MapDirections.directionsMap.clearOverlays();
    MapDirections.clearErrorMessages();
    MapDirections.directionMapLoaded = true;
    jQuery('#directionsPanel').html(jQuery('#dirDisclaimer'));

    // Publish directions view [direction results] event
    if(MapDirections.overrideReportingInfo) {
      DGPWidgetsCommon.publishView('HoursAndDirections', 'DrivingDirections_locationHours_results', 'DrivingDirections_results');
    } else {
      DGPWidgetsCommon.publishView('HoursAndDirections', 'DirectionsResults_mapLocator', 'DirectionsResults_mapLocator');
    }

    if (MapDirections.directionsPinSrc) { // only set for IE, which doesn't handle the transparent PNG delivered by Google
      (function() {
        var MAXTRIES=10000,tries=0;
        function reschedule() {setTimeout(imageReplacer,1);}
        function isOurImage(current,expected) {
          function pathEnd(path) { return path.split('/').pop(); }
          return pathEnd(current) == pathEnd(expected);
        }
        function imageReplacer() {
          /* Trying to be extra diligent about replacing the image:
           *
           * 1. "Poll" (via setTimeout), to avoid replacing the image *too* early
           *    (It's possible that there's an image element with no src yet (?))
           * 2. If the src hasn't been set yet, just reschedule (wait for Google to set it)
           *    and make it invisible to avoid flicker of the non-transparent image
           * 3. When the src *has* been set:
           *    - Is it ours (filename match)?
           *      * Yes, then we're already done
           *      * No, reset it to our known transparent GIF
           * 4. Protect ourselves from unlimited rescheduling with a MAXTRIES sentinel
           */
          var letter = ['A','B'];
          jQuery('#directionsPanel img').each(function(ix) {
            var newSrc = MapDirections.directionsPinSrc.replace('{letter}',[letter[ix]]),
                img = this,curSrc = img.src;
            if (curSrc == '' && (++tries < MAXTRIES)) {
              // Google hasn't set it yet, so reschedule and get out now
              img.style.visibility = 'hidden';
              reschedule();
            } else {
              if (!isOurImage(curSrc,newSrc) || (tries >= MAXTRIES)) {
                img.src = newSrc;
                // allow the image to render before resetting visibility;
                setTimeout(function() {img.style.visibility = 'visible';},1);
              }
            }
          });
        }
        reschedule();
      })();
    }
  },

  /*
   * Handle all errors while submitting get directions form
   */
  handleErrors : function() {
      var code = MapDirections.GDir.getStatus().code, msg;
      switch(code) {
        case G_GEO_UNKNOWN_ADDRESS     : msg = ERRORMESSAGE_LOCATION_NOT_FOUND; code = undefined; break;
        case G_GEO_SERVER_ERROR        : msg = ERRORMESSAGE_NOT_PROCESSED; code = undefined; break;
        case G_GEO_MISSING_QUERY       : msg = ERRORMESSAGE_PARAMETER_MISSING; code = undefined; break;
        case G_GEO_BAD_KEY             : msg = ERRORMESSAGE_INVALID_KEY; code = undefined; break;
        case G_GEO_BAD_REQUEST         : msg = ERRORMESSAGE_BAD_REQUEST; code = undefined; break;
        case G_GEO_UNAVAILABLE_ADDRESS : msg = ERRORMESSAGE_UNAVAILABLE_ADDRESS; code = undefined; break;
        case G_GEO_UNKNOWN_DIRECTIONS  : msg = ERRORMESSAGE_UNKNOWN_DIRECTIONS; code = undefined; break;
        default                        : msg = ERRORMESSAGE_UNKNOWN_ERROR; break;
      }
      MapDirections.showErrorMessage(msg,code);

      if (MapDirections.displayDirectionsOnPopup) {
        PortalPopup.showHideScrollbar();
        jQuery("#childPopup_ScrollingArea").css('top', '0');
    }
  },

  /*
   * Display the error message associated with getting directions
   * from some bad address?
   */
  showErrorMessage : function(message, code) {
    if (typeof code == 'number') {
      message += '\n\n' + ERROR_CODE + ': ' + code;
    } if (MapDirections.errorMessages) {
      jQuery(MapDirections.errorMessages).append('<div>'+message+'</div>').show();
    } else {
      alert(message);
    }
  },

  /*
   * Publish get directions view event
   */
  publishView : function() {
    if(MapDirections.overrideReportingInfo) {
      DGPWidgetsCommon.publishView('HoursAndDirections', 'DrivingDirections_locationHours', 'DrivingDirections');
    } else {
      DGPWidgetsCommon.publishView('HoursAndDirections', 'GetDirections_mapLocator', 'GetDirections_mapLocator');
    }
  },

  /*
   * Shows the getDirections popup Parameters:- 1.dealerIndex : Dealer Index
   */
  showDirectionsPopup : function(dealerIndex,fromAddr) {
    var dealerIdx = dealerIndex + 1;
    var popupBodyObj = jQuery("#popupBody");

    jQuery("div.directionsPrint").removeClass('hideLayer');
    // Sets the header for popup
    jQuery("#popupHeader").html(jQuery("#dealerInfoHeader" + dealerIdx).html());
    popupBodyObj.html("").removeClass('hideLayer').addClass('showElement');
    // Hides the Thank you message
    jQuery("#popupThankYouMessage").removeClass('showElement').addClass('hideLayer');
    // loads 'Get Directions' form in the popup
    fromAddr = (typeof fromAddr == 'string')  ? fromAddr.replace(/^\s+|\s+$/g,'') : '';
    WSCore.load("popupBody", "showPortalMapDirectionsPopup.ajax",
        function() {
          MapDirections.directionsPopupCallBack(dealerIdx,fromAddr);
        });
  },

  /*
   * Shows the popup overlay and getDirectionsPopup Parameters:- 2.dealerIndex :
   * Dealer Index
   */
  directionsPopupCallBack : function(dealerIndex,fromAddr) {
    MapDirections.directionMapLoaded = false;
    var dirLat = jQuery("div.latitude:eq(" + dealerIndex + ")").html();
    var dirLong = jQuery("div.longitude:eq(" + dealerIndex + ")").html();
    // Remove leading and trailing spaces using regex
    var trimLeadingTrailingSpaces = /^\s+(.*?)\s+$/;
    var directionsToAddress = jQuery("#dealerInfoHeader" + dealerIndex  + " .dealerNameInfo").html();
    directionsToAddress = directionsToAddress.replace(trimLeadingTrailingSpaces, "$1");
    jQuery('#popupOverlay').removeClass('hideLayer').addClass('showElement');
    jQuery('#dgpPopup').removeClass('hideLayer').addClass('showElement');
    jQuery('#dirToInput').attr('value', directionsToAddress);
    jQuery('#dirToLatLng').attr('value', new GLatLng(dirLat, dirLong));
    dealerIndex--;
    if (GBrowserIsCompatible()) {
      MapDirections.directionsMap = MapDirections.createMap();
      var directionsMapLatLng = new GLatLng(dirLat, dirLong);
      MapDirections.directionsMap.addOverlay(new GMarker(directionsMapLatLng));
      MapDirections.directionsMap.setCenter(new GLatLng(dirLat, dirLong), 13);

      MapDirections.directionsMap.setUI(MapDirections.getDirectionMapUI(MapDirections.directionsMap));
      jQuery('#dirFromInput').val(fromAddr);
    }
    if(MapDirections.displayDirectionsOnPopup) {
      PortalPopup.showHideScrollbar();
      // At the time of popup load, scrolls the popups to the position 0.
      PortalPopup.scrollTo(0, 'childPopup');
    }
    if (fromAddr) {
        getDirections();
    }
  },

  setOverrideReportingInfo : function(useDefault) {
    MapDirections.overrideReportingInfo = useDefault;
  },

  getDirectionMapUI : function(mapObj){
    var customUI = mapObj.getDefaultUI();
    customUI.controls.maptypecontrol = true;
    customUI.maptypes.physical   = false;
    customUI.controls.scalecontrol = false;
    return customUI;
  },

  setMapUI : function(mapObj) {
    var customUI = mapObj.getDefaultUI();
    customUI.controls.maptypecontrol = false;
    customUI.controls.scalecontrol = false;
    return customUI;
  },

  /*
   * This is being used by DrivingDirections_directions.jsp
   * It creates an instance on GMap2 and then load the directions into it
   */
  showDrivingDirections : function(fromAddress, toAddress, dealerIndex) {
    var directionsToAddress = jQuery("#dealerInfoHeader" + dealerIndex + " .dealerNameInfo").html();

    // Remove leading and trailing spaces using regex
    directionsToAddress = directionsToAddress.replace(/^\s+|\s+$/g, "");

    jQuery('#dirToInput').attr('value', directionsToAddress);

    if (GBrowserIsCompatible()) {
      MapDirections.directionsMap = MapDirections.createMap();
      MapDirections.directionsMap.setUI(MapDirections.setMapUI(MapDirections.directionsMap));
      MapDirections.showDirections(fromAddress, toAddress);
    }
  },

  /*
   * Overriding google styles for Directions start & end box
   */
  overrideGStyles : function() {
    jQuery("#directionsPanel table").css('background', 'transparent');
    jQuery("#directionsPanel table").css('color', '').attr('class','F');
    MapDirections.bindPublishStepBubbleEvent();
  },

  bindPublishStepBubbleEvent : function() {
    jQuery("#directionsPanel table tr").bind("click", function() {
      DGPWidgetsCommon.publishView('HoursAndDirections', 'DrivingDirections_locationHours_stepBubble', 'DrivingDirections_stepBubble');
    });
  }
};

if (jQuery.browser.msie) {
  // Preload substitute images for the directions list.
  // IE has transparency issues, so these *must* be gif files.
  MapDirections.directionsPinSrc = assetServerUrl + '/common/images/mapImages/icon_green{letter}.gif';
}
})();

