

/* An InfoBox is like an info window, but it displays
 * under the marker, opens quicker, and has flexible styling.
 * @param {GLatLng} latlng Point to place bar at
 * @param {Map} map The map on which to display this InfoBox.
 * @param {Object} opts Passes configuration options - content,
 *   offsetVertical, offsetHorizontal, className, height, width
 */
function InfoBox(opts) {
  google.maps.OverlayView.call(this);
  this.latlng_ = opts.latlng;
  this.map_ = opts.map;
  this.title = opts.title;
  this.infoContent = opts.infoContent;
  this.tiderContent = opts.tiderContent;
  this.merContent = opts.merContent;
  this.index = opts.indexVal;
  this.offsetVertical_ = -283;
  this.offsetHorizontal_ = -132;
  this.height_ = 205;
  this.width_ = 218;
  this.logo = opts.logo;
  this.thumb = opts.thumb;
  this.img = opts.img;

  var me = this;
  this.boundsChangedListener_ =
    google.maps.event.addListener(this.map_, "bounds_changed", function() {
      return me.panMap.apply(me);
    });

  // Once the properties of this OverlayView are initialized, set its map so
  // that we can display it.  This will trigger calls to panes_changed and
  // draw.
  this.setMap(this.map_);
}

/* InfoBox extends GOverlay class from the Google Maps API
 */
InfoBox.prototype = new google.maps.OverlayView();

/* Creates the DIV representing this InfoBox
 */
InfoBox.prototype.remove = function() {
  if (this.div_) {
    this.div_.innerHTML = "";
    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
  }
};

InfoBox.prototype.remake = function(opts) {
  google.maps.OverlayView.call(this);
  this.latlng_ = opts.latlng;
  this.map_ = opts.map;
  this.title = opts.title;
  this.infoContent = opts.infoContent;
  this.tiderContent = opts.tiderContent;
  this.merContent = opts.merContent;
  this.index = opts.indexVal;
  this.offsetVertical_ = -283;
  this.offsetHorizontal_ = -132;
  this.height_ = 205;
  this.width_ = 218;

  var me = this;
  this.boundsChangedListener_ =
    google.maps.event.addListener(this.map_, "bounds_changed", function() {
      return me.panMap.apply(me);
    });

  // Once the properties of this OverlayView are initialized, set its map so
  // that we can display it.  This will trigger calls to panes_changed and
  // draw.
  this.setMap(this.map_);
};

/* Redraw the Bar based on the current projection and zoom level
 */
InfoBox.prototype.draw = function() {
  // Creates the element if it doesn't exist already.
  this.createElement();
  if (!this.div_) return;

  // Calculate the DIV coordinates of two opposite corners of our bounds to
  // get the size and position of our Bar
  var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
  if (!pixPosition) return;

  // Now position our DIV based on the DIV coordinates of our bounds
  this.div_.style.width = this.width_ + "px";
  this.div_.style.left = (pixPosition.x + this.offsetHorizontal_) + "px";
  this.div_.style.height = this.height_ + "px";
  this.div_.style.top = (pixPosition.y + this.offsetVertical_) + "px";
  this.div_.style.display = 'block';
};

/* Creates the DIV representing this InfoBox in the floatPane.  If the panes
 * object, retrieved by calling getPanes, is null, remove the element from the
 * DOM.  If the div exists, but its parent is not the floatPane, move the div
 * to the new pane.
 * Called from within draw.  Alternatively, this can be called specifically on
 * a panes_changed event.
 */
InfoBox.prototype.createElement = function() {
  var panes = this.getPanes();
  var div = this.div_;
  if (!div) {
    // This does not handle changing panes.  You can set the map to be null and
    // then reset the map to move the div.
    div = this.div_ = document.createElement("div");
    div.className = "infoWindow";
    div.style.border = "0px none";
    div.style.position = "relative";
    //div.style.background = "url('http://gmaps-samples.googlecode.com/svn/trunk/images/blueinfowindow.gif')";
    div.style.width = this.width_ + "px";
    div.style.height = this.height_ + "px";
    //var contentDiv = document.createElement("div");
    //contentDiv.style.padding = "30px"
    //contentDiv.innerHTML = this.content;

    var closeBtn = document.createElement("a");
    closeBtn.className = "closeBtn";
    closeBtn.href = "javascript:return false;";
    closeBtn.title = "Lukk";
    closeBtn.innerHTML = "x";
    
    var infoWindowTabContainer = document.createElement("div");
    infoWindowTabContainer.className = "infoWindowTabContainer";
    var self = this;
    
    var thumbnail;
    var thumb;
    if(this.thumb.length > 0) {
      thumbnail = new Image();
      thumbnail.alt = this.title;
      thumbnail.src = this.thumb;
      thumbnail.className = "thumbnail";
    }
    if(thumbnail) {
      thumb = document.createElement("a");
      thumb.href = this.img;
      thumb.className = "thumb";
      thumb.title = this.title;
      thumb.appendChild(thumbnail);
      jQuery(thumb).lightBox();
    }
    
    var title;
    if(this.logo != "") {
      title = new Image();
      title.alt = this.title;
      title.src = this.logo;
      title.className = "logo";
    } else {
      title = document.createElement("h2");
      title.innerHTML = this.title;
    }
    
    var tabs = document.createElement("div");
    tabs.className = "tabs";
    
    
    var infoContainer = document.createElement("div");
    infoContainer.id = "info_"+this.index;
    infoContainer.className = "infoContainer";
    infoContainer.innerHTML = this.infoContent;
    
    var tiderContainer = document.createElement("div");
    tiderContainer.id = "tider_"+this.index;
    tiderContainer.className = "tiderContainer";
    tiderContainer.innerHTML = this.tiderContent;
    tiderContainer.style.display = "none";
    
    var merContainer = document.createElement("div");
    merContainer.id = "mer_"+this.index;
    merContainer.className = "merContainer";
    merContainer.innerHTML = this.merContent;
    merContainer.style.display = "none";
    
    var infoBtn = document.createElement("a");
    infoBtn.className = "tabBtn first active";
    infoBtn.href = "javascript:return false;";
    //infoBtn.title = "Kontaktinfo";
    infoBtn.title = "Info";
    infoBtn.innerHTML = "Info";
    infoBtn.onclick = function() {
      
      infoBtn.className = "tabBtn first active";
      infoContainer.style.display = "block";
      if(thumb) thumb.style.display = "block";
      tiderBtn.className = "tabBtn";
      tiderContainer.style.display = "none";
      merBtn.className = "tabBtn last";
      merContainer.style.display = "none";
      
      return false;
    }
    
    var tiderBtn = document.createElement("a");
    tiderBtn.className = "tabBtn";
    tiderBtn.href = "javascript:return false;";
    tiderBtn.title = "Åpningstider";
    tiderBtn.innerHTML = "Tider";
    tiderBtn.onclick = function() {
      infoBtn.className = "tabBtn first";
      infoContainer.style.display = "none";
      if(thumb) thumb.style.display = "none";
      tiderBtn.className = "tabBtn active";
      tiderContainer.style.display = "block";
      merBtn.className = "tabBtn last";
      merContainer.style.display = "none";
      return false;
    }
    
    var merBtn = document.createElement("a");
    merBtn.className = "tabBtn last";
    merBtn.href = "javascript:return false;";
    //merBtn.title = "Mer info";
    merBtn.title = "Kontaktinfo";
    //merBtn.innerHTML = "Mer";
    merBtn.innerHTML = "Kontakt";
    merBtn.onclick = function() {
      infoBtn.className = "tabBtn first";
      infoContainer.style.display = "none";
      if(thumb) thumb.style.display = "none";
      tiderBtn.className = "tabBtn";
      tiderContainer.style.display = "none";
      merBtn.className = "tabBtn last active";
      merContainer.style.display = "block";
      return false;
    }
    
    tabs.appendChild(infoBtn);
    tabs.appendChild(tiderBtn);
    tabs.appendChild(merBtn);
    
    infoWindowTabContainer.appendChild(tabs);
    infoWindowTabContainer.appendChild(title);
    if(thumb) infoWindowTabContainer.appendChild(thumb);
    
    var bottomDiv = document.createElement("div");
    bottomDiv.className = "infoWindowBottom";
    
    var topDiv = document.createElement("div");
    topDiv.className = "infoWindowTop";
    
    function removeInfoBox(ib) {
      return function() {
        ib.setMap(null);
      };
    }

    google.maps.event.addDomListener(closeBtn, 'click', removeInfoBox(this));

    div.appendChild(topDiv);
    div.appendChild(closeBtn);
    infoWindowTabContainer.appendChild(infoContainer);
    infoWindowTabContainer.appendChild(tiderContainer);
    infoWindowTabContainer.appendChild(merContainer);
    div.appendChild(infoWindowTabContainer);
    div.appendChild(bottomDiv);
    div.style.display = 'none';
    panes.floatPane.appendChild(div);
    this.panMap();
  } else if (div.parentNode != panes.floatPane) {
    // The panes have changed.  Move the div.
    div.parentNode.removeChild(div);
    panes.floatPane.appendChild(div);
  } else {
    // The panes have not changed, so no need to create or move the div.
  }
}

/* Pan the map to fit the InfoBox.
 */
InfoBox.prototype.panMap = function() {
  // if we go beyond map, pan map
  var map = this.map_;
  var bounds = map.getBounds();
  if (!bounds) return;

  // The position of the infowindow
  var position = this.latlng_;

  // The dimension of the infowindow
  var iwWidth = this.width_;
  var iwHeight = this.height_;

  // The offset position of the infowindow
  var iwOffsetX = this.offsetHorizontal_;
  var iwOffsetY = this.offsetVertical_;

  // Padding on the infowindow
  var padX = 40;
  var padY = 40;

  // The degrees per pixel
  var mapDiv = map.getDiv();
  var mapWidth = mapDiv.offsetWidth;
  var mapHeight = mapDiv.offsetHeight;
  var boundsSpan = bounds.toSpan();
  var longSpan = boundsSpan.lng();
  var latSpan = boundsSpan.lat();
  var degPixelX = longSpan / mapWidth;
  var degPixelY = latSpan / mapHeight;

  // The bounds of the map
  var mapWestLng = bounds.getSouthWest().lng();
  var mapEastLng = bounds.getNorthEast().lng();
  var mapNorthLat = bounds.getNorthEast().lat();
  var mapSouthLat = bounds.getSouthWest().lat();

  // The bounds of the infowindow
  var iwWestLng = position.lng() + (iwOffsetX - padX) * degPixelX;
  var iwEastLng = position.lng() + (iwOffsetX + iwWidth + padX) * degPixelX;
  var iwNorthLat = position.lat() - (iwOffsetY - padY) * degPixelY;
  var iwSouthLat = position.lat() - (iwOffsetY + iwHeight + padY) * degPixelY;

  // calculate center shift
  var shiftLng =
      (iwWestLng < mapWestLng ? mapWestLng - iwWestLng : 0) +
      (iwEastLng > mapEastLng ? mapEastLng - iwEastLng : 0);
  var shiftLat =
      (iwNorthLat > mapNorthLat ? mapNorthLat - iwNorthLat : 0) +
      (iwSouthLat < mapSouthLat ? mapSouthLat - iwSouthLat : 0);

  // The center of the map
  var center = map.getCenter();

  // The new map center
  var centerX = center.lng() - shiftLng;
  var centerY = center.lat() - shiftLat;

  // center the map to the new shifted center
  map.setCenter(new google.maps.LatLng(centerY, centerX));

  // Remove the listener after panning is complete.
  google.maps.event.removeListener(this.boundsChangedListener_);
  this.boundsChangedListener_ = null;
};
