var g_info_window_is_for = null;
var g_cluster = null;
var g_autors = {};
var g_rutes = {};
var g_espais = {};
var g_map = null;

function slugify(text) {
    text = text.replace(/[^-a-zA-Z0-9\s]+/ig, '');
    text = text.replace(/-/gi, "_");
    text = text.replace(/\s/gi, "-");
    return text.toLowerCase();
}

Shadowbox.init({
    handleResize:"resize",
    enableKeys:false
});

function RegionControl(regions) {
    this.regions_ = regions;
}

RegionControl.prototype = new GControl();

RegionControl.prototype.initialize = function(map) {
    var container = $('<div></div>');
    $.each(this.regions_, function() {

        var region = this;
        if (!region.name) {
            return;
        }

        var button = $('<div></div>'); //document.createElement('div');
        button.addClass('map-region-button').append(region.name);

        button.mousedown(function() {
            button.addClass('pressed');
        });

        button.mouseup(function() {
            button.removeClass('pressed');
        });

        button.mouseleave(function() {
            button.removeClass('pressed');
        });

        button.click(function() {
            map.setCenter(region.bounds.getCenter());
            map.setZoom(map.getBoundsZoomLevel(region.bounds));
        });

        container.append(button);
    });

    container.appendTo(map.getContainer());
    return container.get(0);
};

RegionControl.prototype.getDefaultPosition = function() {
    return new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(10, 20));
};

/**
 * @author Marco Alionso Ramirez, marco@onemarco.com
 * @url http://onemarco.com
 * @version 1.0
 * This code is public domain
 */

/**
 * The Tooltip class is an addon designed for the Google Maps GMarker class.
 * @constructor
 * @param {GMarker} marker
 * @param {String} text
 * @param {Number} padding
 */
function Tooltip(marker, text, padding, cls){
    this.marker_ = marker;
    this.text_ = text;
    this.padding_ = padding;
    this.class_ = cls||"";
}

Tooltip.prototype = new GOverlay();

Tooltip.prototype.initialize = function(map){
    var div = $('<div></div>');

    div
    .append(this.text_)
    .addClass('tooltip ' + this.class_)
    .css('position', 'absolute')
    .hide()
    .appendTo(map.getPane(G_MAP_FLOAT_PANE));

    this.map_ = map;
    this.div_ = div;
};

Tooltip.prototype.remove = function(){
    this.div_.remove();
};

Tooltip.prototype.copy = function(){
    return new Tooltip(this.marker_, this.text_, this.padding_);
};

Tooltip.prototype.redraw = function(force){
    if (!force) {return;}
    var markerPos = this.map_.fromLatLngToDivPixel(this.marker_.getPoint());
    var icon = this.marker_.getIcon();
    var xPos = markerPos.x + icon.iconSize.width - icon.iconAnchor.x + 3;
    var height = this.div_.height() + parseInt(this.div_.css('padding-top')) + parseInt(this.div_.css('padding-bottom'));
    var yPos = markerPos.y - ((icon.iconSize.height + 12) / 2) - (height / 2);
    this.div_.css('top', yPos + 'px');
    this.div_.css('left', xPos + 'px');
};

Tooltip.prototype.show = function(){
    this.div_.show();
};

Tooltip.prototype.hide = function(){
    this.div_.hide();
};

function set_visible(item, visible) {
    if (visible) {
        item.show();
    } else {
        if (g_info_window_is_for == item) {
            g_map.closeInfoWindow();
        }
        item.hide();
    }
}

function add_flag(obj, flag) {
    if (obj.flags[flag])
        return;
    obj.flags[flag] = true;
    for (var id in obj.flags) {
        set_visible(obj.marker, false);
        break;
    }
}

function remove_flag(obj, flag) {
    if (!obj.flags[flag])
        return;
    delete obj.flags[flag];
    for (var id in obj.flags) {
        return
    }
    set_visible(obj.marker, true);
}

function open_ruta(ruta_pk) {
    var ruta = g_rutes[ruta_pk];
    var autor = g_autors[ruta.autor];
    $('<div class="detalls-ruta"></div>').load("/mapa/ruta/" + ruta_pk + "/" + slugify(autor.nom) + "/" + slugify(ruta.nom),
        function(response, status, req) {
            g_map.openInfoWindow(g_rutes[ruta_pk].marker.getBounds().getCenter(), this);
        }
    );
}

function open_espai(espai_pk) {
    var espai = g_espais[espai_pk];
    var autor = g_autors[espai.autor];
    var marker = espai.marker;

    if (marker == g_info_window_is_for) {
        return;
    }

    g_info_window_is_for = marker;

    $('li.highlight').removeClass('highlight').css("color", '');

    var name_element = $(".espai#espai-"+espai_pk);

    name_element.closest("li").addClass("highlight");
    
    name_element.parents('li').addClass('open').children('.collapsible').show();

    var loaded = false;
    var bg = name_element.css("background-color");
    var fg = name_element.css("color");
    
    var pulsate = function () {
        if (!loaded) {
            name_element
                .animate({color: bg})
                .animate({color: fg}, pulsate);
        }
    };
    setTimeout(pulsate, 500);

    $('<div class="detalls-espai"></div>').load("/mapa/espai/" + espai_pk + "/" + slugify(autor.nom) + "/" + slugify(espai.nom),
        function(response, status, req) {
            marker.openInfoWindow(this);
            $(this).find('div.text,div.context').find("a").click(function() {
                window.open($(this).attr("href"));
                return false;
            });
            $(this).find("div.imatge a").each(function() {
                Shadowbox.setup(this);
            });
            loaded = true;
        }
    );
}

function anar_punt(ruta_pk, espai_pk, offset) {
    var espais = g_rutes[ruta_pk].espais;

    for (var index = 0; index <= espais.length; ++index) {
        if (espais[index] == espai_pk) {
            break;
        }

        if (index == espais.length) {
            return;
        }
    }

    var new_pk = espais[index + offset];
    if (new_pk !== null && new_pk !== undefined) {
        open_espai(new_pk);
    }
}

function parada_anterior_de(ruta_pk, espai_pk) {
    anar_punt(ruta_pk, espai_pk, -1);
}

function parada_seguent_de(ruta_pk, espai_pk) {
    anar_punt(ruta_pk, espai_pk, 1);
}

function tiltCamera() {
    g_map.getEarthInstance(function (ge) {
        if (!ge) {
            return;
        }

        var lookAt = ge.getView().copyAsLookAt(ge.ALTITUDE_RELATIVE_TO_GROUND);
        lookAt.setTilt(45.0);
        ge.getView().setAbstractView(lookAt);
    });
}

function init_map() {
    g_map = new google.maps.Map2(document.getElementById("mapa"));
    g_map.addControl(new google.maps.LargeMapControl());
    g_map.addControl(new google.maps.MapTypeControl());
    g_map.getMapTypes().length = 0;
    g_map.addMapType(google.maps.PHYSICAL_MAP);
    g_map.addMapType(google.maps.NORMAL_MAP);
    g_map.addMapType(google.maps.SATELLITE_MAP);
    g_map.addMapType(google.maps.HYBRID_MAP);
    g_map.addMapType(google.maps.SATELLITE_3D_MAP);
    g_map.setMapType(google.maps.PHYSICAL_MAP);
    g_map.enableScrollWheelZoom();

    google.maps.Event.addListener(g_map, 'maptypechanged', function() {
        if (g_map.getCurrentMapType() == google.maps.SATELLITE_3D_MAP) {
            setTimeout(tiltCamera, 2000);
        }
    });

    g_map.setCenter(new google.maps.LatLng(0.0, 0.0), 13);
}

function paint_autors() {
    if (!g_map) {
        return;
    }
    
    var bounds = new google.maps.LatLngBounds();

    var icon = new google.maps.Icon();
    icon.image = '/media/img/marker-multiple.png';
    icon.shadow = '/media/img/marker-sombra.png';
    icon.iconSize = new google.maps.Size(45, 57);
    icon.shadowSize = new google.maps.Size(72, 56);
    icon.iconAnchor = new google.maps.Point(22, 56);
    icon.infoWindowAnchor = new google.maps.Point(23, 15);

    var markers = [];

    $.each(data, function() {
        var autor = this;
        g_autors[autor.pk] = autor;

        var icon = new GIcon();
        icon.image = "/media/img/gen/marker_" + autor.pk + ".png";
        icon.shadow = "/media/img/marker-sombra.png";
        icon.iconSize = new google.maps.Size(45, 57);
        icon.shadowSize = new google.maps.Size(72, 56);
        icon.iconAnchor = new google.maps.Point(22, 56);
        icon.infoWindowAnchor = new google.maps.Point(23, 15);

        autor.icon = icon;

        $.each(autor.espais, function() {
            var espai = this;
            
            this.latlng = new google.maps.LatLng(espai.lat, espai.lng);
            var marker = new google.maps.Marker(espai.latlng, {icon: autor.icon});
            var tt = '<span class="autor-name">' + autor.nom + '</span><br />' +
            '<span class="espai-name">' + espai.nom + '</span>';

            marker.tooltip = new Tooltip(marker, tt, 4);
            marker.autor_pk = autor.pk;

            g_espais[espai.pk] = {nom: espai.nom, autor: autor.pk , marker: marker, ambit: espai.ambit, flags: {}};
            
            google.maps.Event.addListener(marker, 'click', function() {
                $('#autors').scrollTo($(".espai#espai-"+espai.pk).parents('div.autor'), {duration:500});
                open_espai(espai.pk);
            });

            google.maps.Event.addListener(marker, 'infowindowclose', function() {
                $(".espai#espai-"+espai.pk).closest("li").removeClass("highlight").css('color', '');
                g_info_window_is_for = null;
            });

            google.maps.Event.addListener(marker, 'mouseover', function(latlng) {
                this.tooltip.show();
            });

            google.maps.Event.addListener(marker, 'mouseout', function(latlng) {
                this.tooltip.hide();
            });

            g_map.addOverlay(marker.tooltip);

            markers.push(marker);

            bounds.extend(this.latlng);
        });

        $.each(autor.rutes, function() {
            var params = this.encoded_line;
            params["color"] = autor.color;
            params["weight"] = 5;
            params["opacity"] = 0.75;

            var ruta = {
                nom: this.nom,
                autor: autor.pk,
                espais: this.espais,
                marker: new google.maps.Polyline.fromEncoded(params),
                flags: {}
            };

            g_map.addOverlay(ruta.marker);
            g_rutes[this.pk] = ruta;
        });
    });

    for (var i = markers.length - 1; i >= 0; --i) {
        g_map.addOverlay(markers[i]);
    }

    g_cluster = new ClusterMarker(g_map, {
        clusterMarkerIcon:icon,
        markers:markers,
        showToolTips:false,
        clusterMarkerMouseOver: function(args) {
            var cluster = args.clusterMarker;
            var markers = args.clusteredMarkers;

            var autors = {};
            var autor_count = 0;
            for (var i=markers.length-1; i>=0; --i) {
                var pk = markers[i].autor_pk;
                if (!autors[pk]) {
                    autor_count++;
                    autors[pk] = 1;
                }
            }

            var espai_count = markers.length;

            var text = espai_count + (espai_count == 1 ? ' espai ' : ' espais ');
            if (autor_count == 1)
                text += "d'1 autor";
            else if (autor_count == 11)
                text += "d'11 autors";
            else
                text += "de " + autor_count + " autors";
            text += '<br /><span class="instructions">(clic per apropar-se)</span>';

            cluster.mlc_tooltip = new Tooltip(cluster, text, 4);
            g_map.addOverlay(cluster.mlc_tooltip);
            cluster.mlc_tooltip.show();
        },
        clusterMarkerMouseOut: function(args) {
            var cluster = args.clusterMarker;

            cluster.mlc_tooltip.hide();
            g_map.removeOverlay(cluster.mlc_tooltip);
            delete cluster.mlc_tooltip;
        },
        clusterMarkerRemove: function(args) {
            var cluster = args.clusterMarker;

            if (cluster.mlc_tooltip) {
                g_map.removeOverlay(cluster.mlc_tooltip);
            }
            delete cluster.mlc_tooltip;
        }
    });

    g_cluster.fitMapToMarkers();

    var regions = [
        {name: 'Món', bounds:bounds},
        {name: 'Països Catalans', bounds:new GLatLngBounds(new GLatLng(37.7, -1.5), new GLatLng(43.2, 4.73))},
        {name: 'Catalunya', bounds:new GLatLngBounds(new GLatLng(40.5, 0.2), new GLatLng(42.8, 3.4))}
    ];

    g_map.addControl(new RegionControl(regions));

    g_map.savePosition();
}

function alternate_row_colours() {
    $('#autors').find('ul').each(function() {
        var i = 0;
        $(this).children('li.espai:not(.filtered)').each(function() {
            $(this)
            .removeClass('even odd')
            .addClass((++i % 2 === 0) ? 'even' : 'odd');
        });
    });
}

function cerca() {
    // remove any author filter
    $('#filtre input[type=checkbox]').attr('checked', true).change();

    var term = $('span#litquery>input').val();
    
    $.getJSON("/mapa/cerca", {q:term}, function(espais) {
        $('div.autor').addClass('filtered');
        $('ul.ambits,ul.rutes,ul.espais').addClass('filtered');
        $('li.ambit,li.ruta,li.espai').addClass('filtered');

        var id;
        for (id in g_espais) {
            add_flag(g_espais[id], "filtered");
        }
        for (id in g_rutes) {
            add_flag(g_rutes[id], "filtered");
        }

        for (var i=0; i<espais.length; ++i) {
            var espai_id = espais[i];
            // TODO: set any containing rutes visible
            remove_flag(g_espais[espai_id], "filtered");
            var name = $('.espai#espai-' + espai_id);
            name.show().removeClass('filtered');
            name.parents("ul,li,div.autor").removeClass('filtered');
            name.parents("li").addClass('open').children('.collapsible').show();
        }

        g_cluster.refresh(true);
        alternate_row_colours();
    });
}

function uncerca() {
    $('span#litquery>input').val("");

    $('div.autor').removeClass('filtered');
    $('ul.ambits,ul.rutes').removeClass('filtered');
    $('li.ambit,li.ruta,li.espai').removeClass('filtered');

    var id;
    for (id in g_espais) {
        remove_flag(g_espais[id], "filtered");
    }
    for (id in g_rutes) {
        remove_flag(g_rutes[id], "filtered");
    }

    g_cluster.refresh(true);
    alternate_row_colours();
}

function inline_input_label(selector, label) {
    var self = $(selector);
    if (self.val() === '') {
        self.val(label);
    }

    self.focus(function() {
        if(self.val() === label) {
            self.val('').addClass('focused');
        }
    }).blur(function() {
        if(self.val() === '') {
            self.val(label).removeClass('focused');
        }
    });
}

$(function() {
    init_map();
    paint_autors();
    
    $('input[type=checkbox].ruta').click(function() {
        var ruta = g_rutes[$(this).val()];
        
        // remember that we negate checked because the checkbox hasn't
        // updated yet, but we know it will
        var checked = ! $(this).attr("checked");

        if (checked) {
            $(this).parents('li.ruta').removeClass('disabled');
            remove_flag(ruta, "unchecked");
            $.each(ruta.espais, function(espai_idx, espai_id) {
                remove_flag(g_espais[espai_id], "unchecked");
            });
        } else {
            add_flag(ruta, "unchecked");
            $.each(ruta.espais, function(espai_idx, espai_id) {
                add_flag(g_espais[espai_id], "unchecked");
            });
            var li = $(this).parents('li.ruta');
            li.addClass('disabled')
              .removeClass('open')
              .find('.collapsible').hide();
        }

        g_cluster.refresh(true);
    });

    $('input[type=checkbox].ruta').each(function() {
        var real = $(this);
        var fake = $('<span class="checkbox"></span>');
        
        fake.click(function() {
            real.click();
            fake.toggleClass('checked');
        });

        if (real.attr('checked')) {
            fake.addClass('checked');
        }
        
        real.before(fake).css('display', 'none');
    });

    $('.triangle').click(function() {
        var e = $(this);
        if (e.parents('.disabled').size() !== 0) {
            return;
        }
        e.parent('li').toggleClass('open').children('.collapsible').toggle();
    });

    $('li.espai').click(function() {
        var id = $(this).attr('id').split('-')[1];
        open_espai(id);
        return false;
    });

    $('select#tipo-veure').change(function() {
        $('div.autor').removeClass('unseen');
        $('li.ambit').removeClass('unseen').css("border-bottom", "");

        $.each(g_rutes, function(ruta_id, ruta) {
            remove_flag(ruta, "unseen");
        });

        $.each(g_espais, function(espai_id, espai) {
            remove_flag(espai, "unseen");
        });

        var ambit = $(this).val();
        if (ambit == "tot") {
            g_cluster.refresh(true);
            return;
        }

        $('li.ambit:not(.'+ambit+')').addClass('unseen');
        $('li.ambit').css('border-bottom', '0');
        $('div.autor:not(:has(li.ambit.'+ambit+'))').addClass('unseen');

        if (ambit == "rutes") {
            var espais_in_rutes = {};

            $.each(g_rutes, function(ruta_id, ruta) {
                $.each(ruta.espais, function(espai_idx, espai_id) {
                    espais_in_rutes[espai_id] = true;
                });
            });

            $.each(g_espais, function(espai_id, espai) {
                if (!espais_in_rutes[espai_id]) {
                    add_flag(espai, "unseen");
                }
            });
        } else {
            var amb = ambit == "espais" ? 'el' : 'xp';
            
            $.each(g_rutes, function(ruta_id, ruta) {
                add_flag(ruta, "unseen");
                $.each(ruta.espais, function(espai_idx, espai_id) {
                    add_flag(g_espais[espai_id], "unseen");
                });
            });

            $.each(g_espais, function(espai_id, espai) {
                if (amb == espai.ambit)
                    remove_flag(espai, "unseen");
                else
                    add_flag(espai, "unseen");
            });
        }

        g_cluster.refresh(true);
    });

    $('span.clearable input').after($('<span class="clearbutton" />').click(function() {
        uncerca();
        $(this).parent('span.clearable').find('input').val('').blur();
        $(this).hide();
    }));

    $('span#litquery span.clearbutton').hide();

    var key_press_search_delay = 0;
    $('span#litquery>input').val("");
    $('span#litquery>input').keyup(function(event) {
        clearTimeout(key_press_search_delay);
        var self = $(this);

        if (self.val() == "") {
            self.removeClass("cancel");
            $('span#litquery span.clearbutton').hide();
            uncerca();
            return;
        } else {
            $('span#litquery span.clearbutton').show();
            self.addClass("cancel");
        }

        if (event && event.keyCode == '13') {
            cerca();
        } else {
            key_press_search_delay = setTimeout(cerca, 1000);
        }
    });

    $('span#litquery>input').focus(function() {
        this.select();
    });

    $('#filtre input[type=checkbox]').change(function() {
        var id = $(this).attr('value');

        var op;

        if ($(this).attr('checked')) {
            $('div.autor#autor-'+id).removeClass('deselected');
            op = remove_flag;
        } else {
            $('div.autor#autor-'+id).addClass('deselected');
            op = add_flag;
        }

        $.each(g_autors[id].espais, function() {
            op(g_espais[this.pk], "deselected");
        });

        $.each(g_autors[id].rutes, function() {
            op(g_rutes[this.pk], "deselected");
        });
        
        g_cluster.refresh(true);
    });

    $('#tots').mousedown(function() {$(this).attr('src', '/media/img/btn-tots-down.png');});
    $('#tots').mouseup(function() {$(this).attr('src', '/media/img/btn-tots.png');});
    $('#tots').click(function() {
        $('#filtre input[type=checkbox]').attr('checked', true).change();
    });

    $('#cap').mousedown(function() {$(this).attr('src', '/media/img/btn-cap-down.png');});
    $('#cap').mouseup(function() {$(this).attr('src', '/media/img/btn-cap.png');});
    $('#cap').click(function() {
        $('#filtre input[type=checkbox]').attr('checked', false).change();
    });

    $('#fet').mousedown(function() {$(this).attr('src', '/media/img/btn-fet-down.png');});
    $('#fet').mouseup(function() {$(this).attr('src', '/media/img/btn-fet.png');});
    $('#fet').click(function() {$('#tria-autors').click();});

    $('#filtre a.autor-name').click(function() {
        var checked = $('#filtre input[type=checkbox]:checked').size();

        if (checked == 1 && $(this).siblings('input[type=checkbox]').attr('checked') === true) {
            $('#filtre input[type=checkbox]').attr('checked', true).change();
        } else {
            var cb = $(this).siblings('input[type=checkbox]').get(0);

            if ($(cb).attr('checked') === false) {
                $(cb).attr('checked', true).change();
            }

            $('#filtre input[type=checkbox]')
                .filter(function() {return this != cb;})
                .attr('checked', false).change();
        }
        return false;
    });

    $('#tria-autors').click(function() {
        if (!$(this).hasClass('open')) {
            $('#filtre').css('display', 'block');
            // XXX: this should be done through CSS but IE7 works better with IMG here
            $(this).addClass('open').find('img').attr('src','/media/img/flecha-marron.png');
        } else {
            $('#filtre').css('display', 'none');
            // XXX: also this
            $(this).removeClass('open').find('img').attr('src','/media/img/flecha-blanca.png');
        }
    });

    $('select#tipo-busqueda').change(function() {
        var geo = $(this).val() == "geo";
        $('span#litquery').css('display', geo ? 'none' : 'inline');
        $('span#geoquery').css('display', geo ? 'inline' : 'none');

        uncerca();

        $('span#litquery>input').val('').blur();
        $('span#geoquery>input').val('').blur();
    });

    $('span#geoquery>input').geo_autocomplete(new google.maps.Geocoder(), {
        selectFirst: false,
        minChars: 3,
        cacheLength: 50,
        width: 200,
        scroll: true,
        scrollHeight: 330,
        language: 'ca'
    }).result(function(event, data) {
        var vp = data.geometry.viewport;
        var ne = vp.getNorthEast();
        var sw = vp.getSouthWest();

        var bounds = new google.maps.LatLngBounds(
            new google.maps.LatLng(sw.lat(), sw.lng()),
            new google.maps.LatLng(ne.lat(), ne.lng()));
                
        g_map.setCenter(bounds.getCenter());
        g_map.setZoom(g_map.getBoundsZoomLevel(bounds));

        $('span#geoquery>input').val('');
    });

    alternate_row_colours();

    inline_input_label('#litquery>input', 'Cerca autors, obres, textos...');
    inline_input_label('#geoquery>input', 'Cerca llocs');
});

