function bind (scope, fn) {
    return function() {
        fn.apply(scope, arguments)
    };
}

Function.prototype.andThen=function(g) {
  var f=this;
  return function() {
    f();g();
  }
};


// preinitialize the address array
if(typeof(gm_addressArray)!="object") gm_addressArray = new Array();
gm_controls = {};
mapobj = null;



svClient = null;
window.streetView = null;


/**
 * Open all maps on a page (useless)
 *
 * @author Andreas Gohr <gohr@cosmocode.de>
 */
function gm_showall(){
    $('div.google_map').each(function(){
        if(this.style.display == "none") gm_toggle(this.id.substr(4));
    });
}

/**
 * Hide all maps on a page (useless)
 *
 * Called in parent
 *
 * @author Andreas Gohr <gohr@cosmocode.de>
 */
function gm_hideall(){
    $('div.google_map').each(function(){
        if(this.style.display != "none") gm_toggle(this.id.substr(4));
    });
}

/**
 * show/hide google map container with the id gmId;
 * the initialization function for the google maps instance is executed only once per instance
 *
 * Called in parent
 *
 * @author tilo <baller@cosmocode.de>
 * @author Andreas Gohr <gohr@cosmocode.de>
 */
function gm_toggle(gmId) {
  if (typeof(gmId) == 'undefined') gmId="";

  var gm_container = document.getElementById("gmap"+gmId); // catch the google map container
  if(!gm_container) return;
  if (gm_container.style.display == "none") { // gm container is hidden
    var container = $(gm_container).find('iframe')[0];
    if(container.src.match(/blank\/*/)){
        container.src = BASE_URL+'index.php/gmap/index/'+container.id+'/'+gmId;
    }
    gm_container.style.display = "";
  } else { // gm container is shown
    gm_container.style.display = "none";
  }
  
}


/**
 * create a custom marker at the specified point and puts an click event on it to show more information
 *
 * Called in iframe
 *
 * @author tilo <baller@cosmocode.de>
 */
function gm_createMarker(point, address) {
    var index = address['index'];
    var markerInfo = address['info'];
    var shopIsPremium = address['isPremium'];
    var enableStreetview = address['enableStreetview'];

    var baseIcon = new GIcon();
    baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
    baseIcon.iconSize = new GSize(20, 34);
    baseIcon.shadowSize = new GSize(37, 34);
    baseIcon.iconAnchor = new GPoint(9, 34);
    baseIcon.infoWindowAnchor = new GPoint(9, 2);
    baseIcon.infoShadowAnchor = new GPoint(18, 25);

    var icon = new GIcon(baseIcon);
    if(parent) BASE_URL = parent.BASE_URL;
    var vip = '';
    if(shopIsPremium) vip='vip';
    icon.image = BASE_URL+'static/images/markers/marker'+index+vip+'.png';
    var marker = new GMarker(point, { icon: icon, zIndexProcess: function() {return shopIsPremium ? parseInt(Math.random()*100) : 1} } );
    if(parseInt(map.getContainer().style.height) > 120 && index > 0) {
        GEvent.addListener(marker, "click", function() {
            streetView.setTargetBalloon(index);
            streetView.setupResultAction(sv_response_success, sv_response_error, {});
            
            var open_fn_callback = function () {
                if ( enableStreetview == true) {
                    streetView.checkLocation(point);
                }
            };
            //marker.openInfoWindowHtml(markerInfo, {onOpenFn: open_fn_callback});
            map.openInfoWindowHtml(point, markerInfo,{
                onOpenFn: open_fn_callback
            });

        });
    } else {
        //FIXME redundant stuff
        GEvent.addListener(marker, "click", function() {
            streetView.setTargetBalloon(index);
            streetView.setupResultAction(sv_response_success_no_balloon, sv_response_error, {});
             if ( enableStreetview == true) {
                streetView.checkLocation(point);
             }
        });
    }

    return marker;
}


sv_response_success = function () {
    var sv = streetView;
    var activate_link = sv_set_balloon_controls(sv);
    if ( sv.isActive() == true ) {
        text_content = document.createTextNode(lang.line('streetview:button1:state2'));
        activate_link(text_content);
        sv.showPanorama();
    } else {
        text_content = document.createTextNode(lang.line('streetview:button1:state1'));
        activate_link(text_content);
    }
}

sv_response_error = function () {
   var sv = streetView;
   if ( sv.isActive() == true ) {
       sv.hidePanorama();
   }
}

sv_dynamic_base_height = function() {
    var element = document.getElementById("google_map_container");
    return element.style.height;
}

//FIXME redundant stuff
sv_response_success_no_balloon = function () {
    var sv = streetView;
    if ( sv.isActive() == true ) {        
        sv.hidePanorama();
    } else {
        //sv.setBaseHeight(window.innerHeight);
        sv.showPanorama();
    }
}


function sv_set_balloon_controls(sv)
{
    var index = sv.getTargetBalloonId();
    var target =  document.getElementById(index);
    if ( target != null ) {
        link = document.createElement("a");
        link.className = "tlf-streetview-link";
        link.id = sv.getToggleButtonId();
        var button = link;

        return function(text_content){
            link.appendChild(text_content);

            link.onclick = function() {
                if (sv.isActive() == false) {
                   sv.showPanorama();
                   link.replaceChild(document.createTextNode(lang.line('streetview:button1:state2')), link.firstChild);
                } else {
                   sv.hidePanorama();
                   link.replaceChild(document.createTextNode(lang.line('streetview:button1:state1')), link.firstChild);
                }
            };
            target.appendChild(link);
        }
    }
    return;
}

/**
 * initialize a new google maps instance
 *
 * Called in iframe
 *
 * @author tilo <baller@cosmocode.de>
 */
function gm_init(gmId) {
    if (!GBrowserIsCompatible()) { // check browser compatibility
        alert("Your Browser is incompatible to this feature.");
        return;
    }
    map = new GMap2(document.getElementById("google_map_container"));

    parent.mapobj = map;
    bounds = new GLatLngBounds(); // dimension object containing all points that will be added

    map.addControl(new GSmallMapControl()); // add zoom and navigation control; alternative: GLargeMapControl()
    map.addControl(new GMapTypeControl()); // add type control (map, satellite

    map.setCenter(bounds.getCenter()); // initialize the map and set center

    if (typeof(parent.gm_controls) != "undefined") {
        gm_controls = parent.gm_controls;
    }

    var addAddressArr = {premium: [], normal: []};
    if (gmId=="") { // if gmId is an empty string place all addresses of the gm address array to map
      instanceCount = parent.gm_addressArray.length - 1;
      if(instanceCount < 0) return;
      for (var i=0; i<=instanceCount; i++) {
        var instance = parent.gm_addressArray[i];
        if (typeof(parent.gm_addressArray[i]) == "object") {
          addressCount = parent.gm_addressArray[i].length - 1;
          if(addressCount < 0) return;
          for (var j=0; j<=addressCount; j++) {
            address = parent.gm_addressArray[i][j];
            if (address['isPremium'])
                addAddressArr.premium.push(address);
            else
                addAddressArr.normal.push(address);
          }
        }
      }
    } else { // just place addresses linked to the specified gm instance
      if (typeof(parent.gm_addressArray[gmId]) == "object") {
        addressCount = parent.gm_addressArray[gmId].length - 1;
        if(addressCount < 0) return;
        for (var n=0; n<=addressCount; n++) {
          address = parent.gm_addressArray[gmId][n];
          if (address['isPremium'])
            addAddressArr.premium.push(address);
          else
            addAddressArr.normal.push(address);
        }
      }
    }
    for (var i=0; i < addAddressArr.normal.length; i++)
      gm_addAddress(addAddressArr.normal[i]); // finally add address to the gm instance
    
    for (var i=0; i < addAddressArr.premium.length; i++)
      gm_addAddress(addAddressArr.premium[i]); // finally add address to the gm instance

    gm_streetview_init("google_streetview_container");
}


function gm_streetview_init(container) {
    var svClient = new GStreetviewClient();
     var params = {
        'parent_id': CONTAINER_ID,
        'streetview_id': container,
        'base_height': 280,
        'streetview_height': 200,
        'streetview_client': svClient
    }
    streetView = new StreetView(params);
    streetView.setDynamicBaseHeight(sv_dynamic_base_height);

    sv_post_queue.process();
}


/**
 * create a custom marker at the specified point and puts an click event on it to show more information
 *
 * Called in iframe
 *
 * @author tilo <baller@cosmocode.de>
 */
function gm_addAddress(address){//xCoord, yCoord, index, markerInfo, shopIsPremium) {
    var trigger_streetview = gm_controls.trigger_streetview || false;
    point = new GLatLng(address['x'], address['y']);
    bounds.extend(point); // add the point to the dimension object

    zoom = 15; // standard zoom level
    if(map.getBoundsZoomLevel(bounds) < zoom) // adjust the best fitting zoom level if smaller than standard zoom
      zoom = map.getBoundsZoomLevel(bounds);
    map.setZoom(zoom);
    //map.addOverlay(gm_createMarker(point, address['index'], address['info'], address['isPremium'])); // add the custom marker
    var marker = gm_createMarker(point, address);
    map.addOverlay(marker); // add the custom marker
    

    
    if ( trigger_streetview == true ) {
        var tmp = function(){GEvent.trigger(marker, "click")};
        sv_post_queue.push(tmp);
    }

    map.setCenter(bounds.getCenter());
}

/**
 * add a new address to address array for later use
 *
 * gmIds can be multiple multiple ids separated by colons
 *
 * called in parent
 *
 * @author tilo <baller@cosmocode.de>
 * @author Andreas Gohr <gohr@cosmocode.de>
 */
function gm_addToAddressArray(gmIds, index, xCoord, yCoord, markerInfo, shopIsPremium) {
    gmIds = (''+gmIds).split(':');
    for(var i=0; i<=gmIds.length; i++){
        var gmId = gmIds[i];

        if (typeof(gm_addressArray[gmId])!="object") // initialize a new entry in the address array if there is no entry for the specified instance id
          gm_addressArray[gmId] = new Array();

        // add information to the address array
        var m = gm_addressArray[gmId].length;
        gm_addressArray[gmId][m] = new Object();
        gm_addressArray[gmId][m]['index'] = index;
        gm_addressArray[gmId][m]['x'] = xCoord;
        gm_addressArray[gmId][m]['y'] = yCoord;
        gm_addressArray[gmId][m]['info'] = markerInfo;
        gm_addressArray[gmId][m]['isPremium'] = shopIsPremium;
        gm_addressArray[gmId][m]['enableStreetview'] = true;
    }
    //delete(i);
}

function gm_setControls(options){
    gm_controls = options;
}

/**
 * toggles the height of the gmap on a shop page
 *
 * @author tilo <baller@cosmocode.de>
 */
var gm_toggleHeight_lock = false;
function gm_toggleHeight() {
    if(gm_toggleHeight_lock) return;

    var $ifrm =  $('#gmap0 iframe');

    var is_expanded =  $ifrm.hasClass("expanded") || false;
    $ifrm.toggleClass("expanded");
    var a_text = "";
    d_height = '-=0';
    i_height = '0';
    if ( is_expanded ) {
        a_text = GMAP_INCREASE_HEIGHT;
        d_height = '-=160px';
        i_height = '120';
    } else {
        a_text = GMAP_DECREASE_HEIGHT;
        d_height = '+=160px';
        i_height = '280';
    }

    gm_toggleHeight_lock = true;

    $ifrm.animate(
        {'height': d_height},
        'slow',
        function(){
            $('#tlf__map > a').text(a_text);


            $('#gmap0 iframe').attr('height', i_height);

            var center = mapobj.getCenter();
            
            var $item = $('#gmap0 iframe').contents().find('#google_map_container');


            if($.browser.msie) 
                var $item = $('#gmap0 iframe').contents().find('#google_map_container');

            $item.css('height', i_height+'px');

            mapobj.checkResize();
            mapobj.setCenter(center);

    
            gm_toggleHeight_lock = false;
            
        }
    );  
}

