// Set up various global variables used across functions
// The Google Map object
var map;
// All our data
var jsonData;
// The current (GMarker) location of the user
var currentLocation = null;
// Array of GMarker objects to contain all of the locations/restaurants of interest
var markerArray = new Array();
markerArray[1] = new Array();
markerArray[2] = new Array();
markerArray[3] = new Array();
markerArray[4] = new Array();
markerArray[5] = new Array();
markerArray[6] = new Array();
markerArray[7] = new Array();
markerArray[8] = new Array();
// Multi level array of disfferent marker groups (restaurant categories)
var markerGroups = new Array();
markerGroups['All'] = new Array();
markerGroups['Burgers'] = new Array();
markerGroups['Grill'] = new Array();
markerGroups['Kebabs'] = new Array();
markerGroups['Fish'] = new Array();
markerGroups['Italian'] = new Array();
markerGroups['Chinese'] = new Array();
markerGroups['Indian'] = new Array();
markerGroups['Alcohol'] = new Array();
markerGroups['Sandwiches'] = new Array();
markerGroups['Sushi'] = new Array();
markerGroups['open'] = new Array();
markerGroups['book'] = new Array();
// string to hold current group
var currentGroup = 'All';
// Array of all side bar html
var sideBarHtml = new Array();
sideBarHtml[1] = new Array();
sideBarHtml[2] = new Array();
sideBarHtml[3] = new Array();
sideBarHtml[4] = new Array();
sideBarHtml[5] = new Array();
sideBarHtml[6] = new Array();
sideBarHtml[7] = new Array();
sideBarHtml[8] = new Array();
// Array of marker id's and the postcodes that they are excluded from
// ie array(0=>array('BN3','BN2')1=>array('BN1'));
var excludePostcodes = new Array();
// Default map zoom
var zoom = 13;
// Instance of local search object to geocode the postcode more accurately
var localSearch = new GlocalSearch();
// set postcode
var postcode;

// a bunch of helper functions

// in_array function to mimic php's
// usage:
// numbers = new Array("one","two","three","four","five");
// alert(numbers.in_array("three")) // should evaluate to true
Array.prototype.in_array = function ( needle )
{
    var len = this.length;
    for ( var x = 0 ; x <= len ; x++ )
    {
        if ( this[x] == needle ) return true;
    }
    return false;
}
// search function to mimic php's
// return key of a value
Array.prototype.search = function ( needle )
{
    var len = this.length;
    for ( var x = 0 ; x <= len ; x++ )
    {
        if ( this[x] == needle ) return x;
    }
    return false;
}

// mimic the php isset function for testing variables
function isset(varname)
{
    return (typeof( window[ varname ] ) != "undefined") ? true : false;
}

// Check for odd or even number returns true on even
// Note: This returns true for 0
function isEven(value)
{
    return (value%2 == 0) ? true : false;
}

// this function is used to sort json data
// usage:
// Sort by price high to low
// homes.sort(sort_by('price', true, parseInt));

// Sort by city, case-insensitive, A-Z
// homes.sort(sort_by('city', false, function(a){return a.toUpperCase()}));

var sort_by = function(field, reverse, primer){

   reverse = (reverse) ? -1 : 1;

   return function(a,b){

       a = a[field];
       b = b[field];

       if (typeof(primer) != 'undefined'){
           a = primer(a);
           b = primer(b);
       }

       if (a<b) return reverse * -1;
       if (a>b) return reverse * 1;
       return 0;
   }
}

// Function to look up LatLng of postcode
function usePointFromPostcode(post_code, callbackFunction)
{
    localSearch.setSearchCompleteCallback(null,
    function()
    {
        if (localSearch.results[0])
        {
            var resultLat = localSearch.results[0].lat;
            var resultLng = localSearch.results[0].lng;
            var point = new GLatLng(resultLat,resultLng);
            //alert(resultLat + ',' + resultLng);
            callbackFunction(point);
        }
        else
        {
            alert("Postcode not found!");
        }
    });

    localSearch.execute(post_code + ", UK");
}

// Function to place marker and center map at the looked up postcode
function setCurrentLocation(point)
{
    // delete marker if already there
    if (currentLocation)
    {
        map.removeOverlay(currentLocation);
    }
    // html for info window
    var func_html ='<div class="bubble">';
        func_html+='<h3>You Are Here!<a href="#search" onClick="map.closeInfoWindow();return false;" class="closeInfoWindow" title="Close"><img src="images/icons/cancel.png" alt="x" /></a></h3>';
        func_html+='<div class="userInfo">';
        func_html+='<p>From the left-hand menu select the category of food you wish to order.</p>';
        func_html+='<p>View different restaurant menus by clicking the "Order Now", "Pre Book" or "View Menu" buttons in the right hand column.</p>';
        func_html+='</div>';
        func_html+='<div class="submit">';
        func_html+='<a href="#search" onClick="map.closeInfoWindow();return false;" class="button buttonPos" title="Close"><img src="images/icons/tick.png" alt="OK" />OK</a>';
        func_html+='</div>';
        func_html+='</div>';

    // Create marker with info window
    currentLocation = createMarkerWithInfo(point,func_html);
    // Add marker to map
    map.addOverlay(currentLocation);
    // Center map on point
    map.setCenter(point, zoom);
    // open info window
    GEvent.trigger(currentLocation, "click");
    // show restaurants in area
    checkPoints();
}

// used to place the currentLocation marker
function createMarkerWithInfo(point,html)
{
    var func_icon = new GIcon();
    func_icon.image = "images/userLocationMarkerRed.png";
    func_icon.shadow = "images/icon32s.png";
    func_icon.iconSize = new GSize(32.0, 32.0);
    func_icon.shadowSize = new GSize(49.0, 32.0);
    func_icon.iconAnchor = new GPoint(16.0, 16.0);
    func_icon.infoWindowAnchor = new GPoint(16.0, 16.0);

    var func_marker = new GMarker(point, func_icon);
    
    GEvent.addListener(func_marker, "click", function()
    {
        func_marker.openInfoWindowHtml(html,{buttons:{close:{height:0,width:22,show:8}}});
    });
    return func_marker;
}

// Get the Distance between 2 points in miles
// return int
function distanceFrom(pointA, pointB)
{
    // Get distance in meters from point a and point b
    func_meters = pointA.distanceFrom(pointB);

    // Convert the distance to miles
    func_miles = func_meters * 0.000621371192;

    return func_miles;
}

// process JSON data make array of all restaurant markers and their information
function loadJSON(json)
{
    // sort json by open or closed
    //json.markers.sort(sort_by('open', true, function(a){return a.toUpperCase()}));
    //alert(json.markers.sort().toString());
    //print_r(json.markers);
    // Iterate through the JSON feed, extracting data elements of interest.
    // As there are 8 sets of markers (one for each mile of delivery radius) loop the whole thing 4 times
    for (var a = 1; a <= 8 ; a++)
    {
        for (var i = 0; i < json.markers.length; i++)
        {
            var func_entry = json.markers[i];
            if(func_entry || func_entry.length != 0)
            {
                var func_point = new GLatLng(func_entry.lat,func_entry.lng);
                var func_logo = func_entry.logo;
                var func_id = func_entry.restaurantId;
                var func_restaurantName = func_entry.restaurantName;
                var func_description = func_entry.description;
                var func_openingTime = func_entry.openingTime;
                var func_minimumOrder = func_entry.minimumOrder;
                var func_typesArray = func_entry.types;
                var func_isOpen = func_entry.isOpen;
                var func_hasPreBooking = func_entry.hasPreBooking;
                var func_deliveryCharge;
                switch(a)
                {
                    case 1:
                        func_deliveryCharge = func_entry.delivery_charge_1;
                        break;
                    case 2:
                        func_deliveryCharge = func_entry.delivery_charge_2;
                        break;
                    case 3:
                        func_deliveryCharge = func_entry.delivery_charge_3;
                        break;
                    case 4:
                        func_deliveryCharge = func_entry.delivery_charge_4;
                        break;
                    case 5:
                        func_deliveryCharge = func_entry.delivery_charge_5;
                        break;
                    case 6:
                        func_deliveryCharge = func_entry.delivery_charge_6;
                        break;
                    case 7:
                        func_deliveryCharge = func_entry.delivery_charge_7;
                        break;
                    case 8:
                        func_deliveryCharge = func_entry.delivery_charge_8;
                        break;
                }               

                // if func_deliveryCharge == x then the restaurant wont deliver that far skip next sections
                if (func_deliveryCharge != 'x')
                {
                    // Create some interesting HTML to appear when a location marker is selected
                    var func_html = '<div class="bubble">';
                        func_html += '<h3>' + func_restaurantName + '<a href="#search" onClick="map.closeInfoWindow();return false;" class="closeInfoWindow" title="Close"><img src="images/icons/cancel.png" alt="x" /></a></h3>';
                        func_html += '<div class="restaurantInfo">';
                        func_html += '<img src="' + func_logo + '" class="restaurantLogo" />';
                        func_html += '<p>' + func_description + '</p>';

                    if(func_openingTime != null)
                    {
                        func_html += '<span class="restaurantInfoLabel">Opening Times:</span> <span class="restaurantInfo">' + func_openingTime + '</span>';
                    }
                    if(func_minimumOrder != null)
                    {
                        func_html += '<span class="restaurantInfoLabel">Minimum Order:</span> <span class="restaurantInfo">&pound;' + func_minimumOrder + '</span>';
                    }
                    if(func_minimumOrder != null)
                    {
                        func_html += '<span class="restaurantInfoLabel">Delivery Cost:</span> <span class="restaurantInfo">&pound;' + func_deliveryCharge + '</span>';
                    }
                    if(func_typesArray.length != 0)
                    {
                        func_html += (func_typesArray.length < 2) ? '<span class="restaurantInfoLabel">Category:</span>': '<span class="restaurantInfoLabel">Categories:</span>' ;
                        func_html += '<span class="restaurantInfo">';
                        for (n=0;n < func_typesArray.length; n++)
                        {
                            func_html += func_typesArray[n] + ', ';
                            // add marker to category groups
                            if (a == 1)
                            {
                                markerGroups[func_typesArray[n]].push(i);
                                markerGroups['All'].push(i);
                                // if its open add it to the open group <- used for re-ordering the sidebar
                                if (func_isOpen == 1)
                                {
                                    markerGroups['open'].push(i);
                                }
                                else
                                {
                                    if(func_hasPreBooking == 1)
                                    {
                                        markerGroups['book'].push(i);
                                    }
                                }
                                // Populate excludePostcodes array
                                excludePostcodes[i] = func_entry.exclude_postcodes;                                
                            }
                        }
                        // lose the last 2 characters to remove , from end of category list
                        func_html = func_html.slice(0,-2);
                        func_html += '</span>';
                    }
                    func_html += '</div>';
                    func_html += '<div class="submit">';
                    if (func_isOpen == 1)
                    {
                        func_html += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2" class="button buttonPos"><img src="images/icons/go.png" />Order Now</a>';
                    }
                    else
                    {
                        if(func_hasPreBooking == 1)
                        {
                            func_html += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2" class="button buttonPos"><img src="images/icons/go.png" />Pre-Book</a>';
                        }
                        else
                        {
                            func_html += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2&m=1" class="button buttonNeg"><img src="images/icons/go_red.png" />View Menu</a>';
                        }
                    }
                    func_html += '</div>';
                    func_html += '</div>';

                    // Call a function to create a marker, then push it into the array of locations
                    var func_marker = createRestaurantMarker(func_point, func_html,a);
                    markerArray[a].push(func_marker);
                    map.addOverlay(func_marker);
                    func_marker.hide();
                    // add to sidebar
                    sideBarHtml[a][i] = '<div class="restaurant" onmouseover="javascript:myTimer=setTimeout(\'myclick(' + a + ',' + i + ')\', 500);" onmouseout="javascript:clearTimeout(myTimer);">';

                    if (func_isOpen == 1)
                    {
                        sideBarHtml[a][i] += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2"><h3>' + func_restaurantName + '</h3></a>';
                        sideBarHtml[a][i] += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2"><img src="' + func_logo + '" class="logo" /></a>';
                    }
                    else
                    {
                        if(func_hasPreBooking == 1)
                        {
                            sideBarHtml[a][i] += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2"><h3>' + func_restaurantName + '</h3></a>';
                            sideBarHtml[a][i] += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2"><img src="' + func_logo + '" class="logo" /></a>';
                        }
                        else
                        {
                            sideBarHtml[a][i] += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2&m=1"><h3>' + func_restaurantName + '</h3></a>';
                            sideBarHtml[a][i] += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2&m=1"><img src="' + func_logo + '" class="logo" /></a>';
                        }
                    }
                    sideBarHtml[a][i]+= '<span><strong>Opening Times:</strong> ' + func_openingTime + '</span><br />';
                    sideBarHtml[a][i] += '<span><strong>min order:</strong> ' + func_minimumOrder + '</span><br />';
                    sideBarHtml[a][i] += '<span><strong>Delivery Charge:</strong> ' + func_deliveryCharge + '</span>';
                    sideBarHtml[a][i] += '<br class="clear" />';

                    if (func_isOpen == 1)
                    {
                        sideBarHtml[a][i] += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2" class="button buttonPos">Order Now</a>';
                    }
                    else
                    {
                        if(func_hasPreBooking == 1)
                        {
                            sideBarHtml[a][i] += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2" class="button buttonPos">Pre-Book</a>';
                        }
                        else
                        {
                            sideBarHtml[a][i] += '<a href="myOrder.php?id=' + func_id + '&d=' + encodeURIComponent(func_deliveryCharge) +'&pc=' + encodeURIComponent(postcode) +'&set=2&m=1" class="button buttonNeg">View Menu</a>';
                        }
                    }
                    sideBarHtml[a][i]+= '</div>';
                }
                else
                {
                    markerArray[a].push('x');
                    sideBarHtml[a][i] = '';
                }
            }
            else
            {
                return;
            }
        }
    }
}
      
/*
* Function that creates a GMarker object for the location of interest, using a custom icon
* @param {GLatLng} point - place to create the marker
* @param {String} html - HTML string containing descriptive content for the InfoWindow
* @param {Int} group -
* @returns GMarker for the location
*/
function createRestaurantMarker(point, html, group)
{
    var func_icon = new GIcon();
    func_icon.image = "images/restaurantMarker.png";
    func_icon.shadow = "images/icon32s.png";
    func_icon.iconSize = new GSize(26.0, 31.0);
    func_icon.shadowSize = new GSize(49.0, 32.0);
    func_icon.iconAnchor = new GPoint(13.0, 16.0);
    func_icon.infoWindowAnchor = new GPoint(13.0, 33.0);

    var func_marker = new GMarker(point, func_icon);
    GEvent.addListener(func_marker, "click", function()
    {
        func_marker.openInfoWindowHtml(html,{buttons:{close:{height:0,width:22,show:8}}});
    });

    return func_marker;
}

// this function shows and hides the points on map and side bar
function checkPoints()
{
    // side bar html
    var func_open_html = '';
    var func_book_html = '';
    var func_html = '';

    // used in postcode filter
    var func_postcode_prefix = postcode.substr(0,3).toUpperCase();
    //alert(func_postcode_prefix);
    // If there are no points in the array, just return
    if (!markerArray || markerArray.length == 0)
        return;

    // hide all markers
    for (var n = 1; n <= 8 ; n++)
    {
        for (i=0 ; i < markerArray[n].length ; i++ )
        {
            // make sure marker is not x'd out
            if(markerArray[n][i] != 'x')
            {
                markerArray[n][i].hide();
            }
        }
    }

    // re-show appropraite markers and build sidebar html 
    // based on filters, distance & open/closed status
    for (var a = 1; a <= 8 ; a++)
    {
        for (var i = 0; i < markerGroups[currentGroup].length; i++)
        {
            var func_marker = markerGroups[currentGroup][i];
            if (currentLocation != null)
            {
                if(markerArray[a].length != 0)
                {
                    if(markerArray[a][func_marker] != 'x')
                    {
                        var distance = distanceFrom(markerArray[a][func_marker].getPoint(),currentLocation.getPoint());

                        if (distance <= (a/2) && distance > ((a/2) - 0.5) && markerArray[a][func_marker].isHidden())
                        {
                            // filter out certain postcodes based on contents of excludePostcodes array
                            if(!excludePostcodes[func_marker].in_array(func_postcode_prefix))
                            {
                                markerArray[a][func_marker].show();
                                if(markerGroups['open'].in_array(func_marker))
                                {
                                    func_open_html += sideBarHtml[a][func_marker];
                                }
                                else
                                {
                                    if(markerGroups['book'].in_array(func_marker))
                                    {
                                        func_book_html += sideBarHtml[a][func_marker];
                                    }
                                    else
                                    {
                                        func_html += sideBarHtml[a][func_marker];
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // add a message to say no restaurants found if sidebar is empty
    if(func_open_html=='' && func_book_html=='' && func_html=='')
    {
        func_html = '<p style="padding:0.5em">Sorry, we dont currently have any restaurants in the '+currentGroup+' category in your area.</p><p style="padding:0.5em">You can tell us about your favourite restaurant using our <a href="contact.html" title="Contact Eat Now">Contact</a> page.';
    }

    $("middlerightwrapper").update(func_open_html+func_book_html+func_html);
    // alternate row colors for the sidebar
    $$('#middlerightwrapper > div:nth-child(even)').each(function(s) {
        s.addClassName('alt');
    });

}

function toggleGroup()
{
    $$('.category').each(function(item)
    {
        item.observe('click', function(ev)
        {
            // remove class name active from links
            $$('.category').invoke('removeClassName','active');

            // set the clicked link to class active
            item.addClassName('active');

            // set current category
            currentGroup = item.id;

            // change heading
            $('mapHeading').update('Map - ' + currentGroup);

            // show markers
            checkPoints();

            // stop link changing pages
            ev.stop();
        })
    });
}

// This function picks up the click and opens the corresponding info window
function myclick(a,i)
{
    GEvent.trigger(markerArray[a][i], "click");
}

// Load function
function load ()
{
    // get postcode from url
    postcode = uri.get("postcode");
    // if no postcode from url get postcode from pre generated form input
    if(!postcode)
    {
        postcode = $F('postcode');
    }

    if (GBrowserIsCompatible())
    {
        map = new GMap2($("map"));
        var customUI = map.getDefaultUI();
        customUI.maptypes.normal = false;
        customUI.maptypes.satellite = false;
        customUI.maptypes.physical = false;
        map.setUI(customUI);

        map.setCenter(new GLatLng(50.820931, -0.139846), zoom);
        map.setMapType(G_HYBRID_MAP);

        // load our restaurants from database
        new Ajax.Request('/json/points.php', {
            method:'get',
            requestHeaders: {Accept: 'application/json'},
            onSuccess: function(transport){
                // this is our restaurant data
                var json = transport.responseText.evalJSON();
                loadJSON(json);

                // now sort out our user location
                // postcode is set then set user location
                if(postcode || postcode.length > 0)
                {
                    //setTimeout('usePointFromPostcode(postcode, setCurrentLocation)', 2000);
                    usePointFromPostcode(postcode, setCurrentLocation);
                }
            }
        });
    }
    else
    {
        alert("Sorry, your browser cannot handle the true power of Google Maps");
    }
}

// Author: Benjamin Carlier, http://benjamincarlier.be/
// usage: var term = uri.get('q'); is like term = $_GET['q']
var uri={
    get:function(id)
    {
        var s=location.search.match('(?:\\?|\&)'+id+'=([^\&]*)');
        return (s)?unescape(s[1].replace(/\+/g," ")):false;
    }
}

function addLoadEvent(func)
{
    var oldonload = window.onload;
    if (typeof window.onload != 'function')
    {
        window.onload = func;
    }
    else
    {
        window.onload = function()
        {
            oldonload();
            func();
        }
    }
}

function addUnLoadEvent(func)
{
    var oldonunload = window.onunload;
    if (typeof window.onunload != 'function')
    {
        window.onunload = func;
    }
    else
    {
        window.onunload = function()
        {
            oldonunload();
            func();
        }
    }
}

addLoadEvent(load);
addLoadEvent(toggleGroup);
addUnLoadEvent(GUnload);