var homeLatLng = null;
var ie6 = $.browser.msie && $.browser.version == 6.0;

function roughBox(latlng) {
    var c = 0.3;
    return new google.maps.LatLngBounds(
        new google.maps.LatLng(latlng.lat() + c, latlng.lng() - c),
        new google.maps.LatLng(latlng.lat() - c, latlng.lng() + c)
    );
}

var current_state = ''
function register_state(state) {
    current_state = state;
    location.hash = '#' + state;
}

$(function() {
    var searchbox_default = 'example: 24 Sussex Drive, Ottawa ON';
    $('#addressbox').val(searchbox_default).bind('focus', function() {
       $(this).addClass('active'); 
       if (this.value == searchbox_default) {
           this.value = '';
       }
    }).bind('blur', function () {
       $(this).removeClass('active');
       if (this.value == '') {
           this.value = searchbox_default;
       }
    });
    
    var geocoder = new google.maps.Geocoder();
    
    
    if (navigator.geolocation) {
        $('#geolocate-span').show();
        $('#geolocate-link').click(function (e) {
            e.preventDefault();
            navigator.geolocation.getCurrentPosition(function(position) {
                var geolocateLatLng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
                geocoder.geocode({'latLng': geolocateLatLng},
                    function(results, status) {
                        get_via_address(results[0].formatted_address, geolocateLatLng, true);
                    });
            });
        });
    }
    
    function get_via_address(address, latlng, geolocated) {
        hide_home_elements();
        homeLatLng = latlng;
        address = address.replace(', Canada', '');
        var getdata = {'lat': latlng.lat(), 'lng': latlng.lng(), 'address': address};
        if (geolocated) {
            getdata['geolocated'] = 1;
        }
        $.getJSON('/place/', getdata, function(data) {
            $('#loader').hide();
            $('#results').replaceWith(data.html);
            eval(data.js);
            $('.election-canvas').show();
            $('#results_for_address').html(address);  
        });
    }
    
    function get_via_slug(slug) {
        hide_home_elements();
        $.getJSON('/place/', {'slug': slug}, function(data) {
            $('#loader').hide();
            homeLatLng = new google.maps.LatLng(data.lat, data.lng);
            $('#results').replaceWith(data.html);
            eval(data.js);
            $('.election-canvas').show()
            $('#results_for_address').html(data.address);
        });
    }
    
    function back_home() {
        $('#results').fadeOut(200, function() {
            $('#results').children().remove();
            $('#home').fadeIn(200);
        });
        $('#logo').animate({'left': 365, 'top': 130});
        $('#addressbox').val(searchbox_default);
        register_state('');
    }
    
    function hide_home_elements() {
        $('#home').fadeOut(500, function() {
            $('#results').fadeIn();
        });
        $('#logo').animate({'left': 0, 'top': 21});
        $('#loader').fadeIn(100);
    }
    
    $('.show_home, #logo').live('click', function (e) {
        e.preventDefault();
        back_home();
    });
    
    $(window).hashchange(function () {
        new_state = location.hash.replace('#', '');
        if (new_state != current_state) {
            if (new_state.length) {
                get_via_slug(new_state);
            }
            else {
                back_home();
            }
        }
    });
    
    if (location.hash) {
        $(window).hashchange();
    }
    
    $('.placeform').submit(function (e) {
        e.preventDefault();
        var v = $('#addressbox').val();
        if (v == searchbox_default || v == "") {
            topBar("Please enter your address.");
            return;
        }
        var geocodeOptions = {'address': v + ', Canada', 'region': 'ca'};
        if (geoipPoint) {
            geocodeOptions.bounds = roughBox(geoipPoint);
        }
        geocoder.geocode(geocodeOptions, function(results, status) {
            var potential_results = []
            $.each(results, function() {
                if (this.types.has('street_address')) {
                    potential_results.push({'address': this.formatted_address, 'latlng': this.geometry.location});
                }
            });
            if (potential_results.length == 1) {
                var r = potential_results[0];
                homeLatLng = r.latlng;
                get_via_address(r.address, r.latlng);
            }
            else if (potential_results.length == 0) {
                topBar("Couldn't find a match for that address. Please try entering your full, standard Canadian street address.");
            }
            else {
                $('#address_options ul').remove();
                var $options_list = $('<ul></ul>')
                $.each(potential_results, function () {
                    $('<li></li>').html(this.address)
                        .data('latlng', this.latlng)
                        .click(function (e) {
                            var $this = $(this);
                            get_via_address($this.html(), $this.data('latlng'));
                            $('#address_options').hide();
                        })
                        .appendTo($options_list);
                });
                $('#address_options').append($options_list).slideDown();
            }
        });
    });
});

function get_coloured_pin(colour) {
    return new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_xpin_letter&chld=pin|+|" + colour.replace('#', '') + "|000000",
            new google.maps.Size(21.0, 34.0),
            new google.maps.Point(0, 0)
    );
}

function hslToRgb(h, s, l){
    var r, g, b;

    if(s == 0){
        r = g = b = l; // achromatic
    }else{
        function hue2rgb(p, q, t){
            if(t < 0) t += 1;
            if(t > 1) t -= 1;
            if(t < 1/6) return p + (q - p) * 6 * t;
            if(t < 1/2) return q;
            if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
            return p;
        }

        var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
        var p = 2 * l - q;
        r = hue2rgb(p, q, h + 1/3);
        g = hue2rgb(p, q, h);
        b = hue2rgb(p, q, h - 1/3);
    }

    var hex = (((r * 255) << 16) | ((g * 255) << 8) | (b * 255)).toString(16);
    while  (hex.length < 6) {
        hex = "0" + hex;
    }
    return '#' + hex;
}

function randRange(min, max) {
    return Math.random() * (max - min) + min;
}
function generateColours(n) {
    var i = 0;
    var colors = [];
    for (i = 0; i <= 1; i+= (1/n)) {
        colors.push(hslToRgb(i, randRange(0.5, 0.99), randRange(0.3, 0.7)));
    }
    return colors;
}


var home_shadow = new google.maps.MarkerImage('/static/img/map_icon_home_shadow.png',
    new google.maps.Size(46.0, 30.0),
    new google.maps.Point(0, 0),
    new google.maps.Point(15.0, 30.0)
);
var home_image = new google.maps.MarkerImage('/static/img/map_icon_home.png',
    new google.maps.Size(30.0, 30.0),
    new google.maps.Point(0, 0)
);
var pin_shadow = new google.maps.MarkerImage("/static/img/map_icon_pin_shadow.png",
    new google.maps.Size(39.0, 34.0),
    new google.maps.Point(0, 0),
    new google.maps.Point(10.5, 34.0)
);

function display_no_election_map() {
    var map_options = {
      zoom: 16,
      center: homeLatLng,
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      mapTypeControl: false
    };
    var map = new google.maps.Map(document.getElementById("noelection_canvas"), map_options);
    var home_marker = new google.maps.Marker({
        position: homeLatLng,
        map: map,
        icon: home_image,
        shadow: home_shadow,
        title: "Your address"
    });

}
function display_election_map(election_id, polling_places) {
    var map_options = {
      zoom: 16,
      center: homeLatLng,
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      mapTypeControl: false
    };
    var $canvas = $("#election_canvas_" + election_id);
    if (polling_places.length > 5) {
        $canvas.addClass('hefty');
    }
    var $infopane = $canvas.find('.infopane_wrap');
    var map = new google.maps.Map($canvas.find('.inner')[0], map_options);
    var home_marker = new google.maps.Marker({
        position: homeLatLng,
        map: map,
        icon: home_image,
        shadow: home_shadow,
        title: "Your address"
    });
    if (ie6) {
        var ie6win = new google.maps.InfoWindow({content: 'You are using Internet Explorer 6.<br>As a result, some things may not work.'});
    }

    var mapBounds = map.getBounds();
    if (!mapBounds) {
        mapBounds = new google.maps.LatLngBounds(homeLatLng, homeLatLng);
    }
    
    var poll_colours = generateColours(polling_places.length);

    $.each(polling_places, function () {
        var poll = this;
        var pollColour = poll_colours.pop();
        var pollMarker = new google.maps.Marker({
            position: this.latlng,
            map: map,
            title: this.name,
            icon: get_coloured_pin(pollColour),
            shadow: pin_shadow
        });
        function show_pane(nopan) {
            if (ie6) {
                // Oh, IE6. Somehow, this make things semi-work.
                ie6win.open(map, pollMarker);
                ie6win.close();
            }
            if (!nopan) {
                map.panTo(poll.latlng);
            }
            var addr = poll.address;
            if (poll.notes) {
                addr += '&nbsp; <span class="aside">' + poll.notes + '</span>';
            }
            $infopane.find('.address').html(addr);
            $infopane.find('.name').html(poll.name);
            $infopane.find('.colourbar').css({'background-color': pollColour});
            $infopane.find('li').remove();
            $.each(poll.times, function () {
                $infopane.find('ul').append($('<li>' + this[0] + '<span class="time">' + this[1] + '</span></li>'));
            });
            if (!$infopane.is(':visible')) {
                $infopane.fadeIn();
            }
        }
        if (ie6) {
            // Even weirder IE6 compatibility! I have no idea why this works.
            setTimeout(function () { 
                show_pane(true);
                $infopane.hide();
            }, 500);
        }
        google.maps.event.addListener(pollMarker, 'click', function() {
            show_pane();
        });
        $('#epp_link_' + this.epp_id).click(function (e) {
            e.preventDefault();
            show_pane();
            if (!$canvas.is(':entirely-in-viewport')) {
                $('html, body').animate({scrollTop: $canvas.offset().top - 5}); 
            }
        });
        $('#epp_marker_' + this.epp_id).css({'background-color': pollColour});
        mapBounds.extend(this.latlng);
    });
    
    if (polling_places.length) {
        var boundsListener = google.maps.event.addListener(map, 'bounds_changed', function (e) {
            // This hocus-pocus is necessary because getZoom() does not immediately reflect
            // changes made by fitBounds
            google.maps.event.removeListener(boundsListener);
            var zoom = map.getZoom();
            if (zoom > 16) {
                map.setZoom(16);
            }
            else if (zoom <= 13 && polling_places.length > 2) {
                var newBounds = new google.maps.LatLngBounds(homeLatLng, homeLatLng);
                newBounds.extend(polling_places[0].latlng);
                newBounds.extend(polling_places[1].latlng);
                map.fitBounds(newBounds);
            }
            else if (zoom < 12) {
                /* boundsListener = google.maps.event.addListener(map, 'bounds_changed', function (e) {
                    google.maps.event.removeListener(boundsListener);
                    if (!map.getBounds().contains(homeLatLng)) {
                        map.setCenter(homeLatLng);
                    }
                }); */
                map.setCenter(homeLatLng);
                map.setZoom(12);
            }
        })
        map.fitBounds(mapBounds);
    }
}
