var geocoder;
var map;
var marker;
var zoomIn;
var zoomOut;
var error;
var fieldset;
var errored =           false;
var regionMarkers =     new Object();
var townMarkers =       new Object();
var userMarkers =       new Object();
var n =                 Number(0);
var activeInfoWindow =  false;
var hasRegions =        false;
var iconPreset =        new GIcon(G_DEFAULT_ICON);
var errorMessage =      false;
iconPreset.iconSize =   new GSize(20,33);
iconPreset.shadow =     "http://www.google.com/mapfiles/shadow50.png";
iconPreset.image =      '/images/chef-marker.png';
iconPreset.infoWindowAnchor = new GPoint(9, 2);
im = new Image();
im.src = '/images/chef-hat.png';
im2 = new Image();
im2.src = '/images/loading.gif';

var loadingImage = function ()
{
    if(!searchContainer.getElement('img'))
    {
        loading = new Element('img',
            {
                'src':      '/images/loading.gif',
                'alt':      'loading',
                'class':    'loading'
            }
        );
        searchContainer.appendText(' ');
        searchContainer.grab(loading);
    }
};

var destroyLoadingImage = function ()
{
    if($defined(searchContainer.getElement('img')))
    {
        searchContainer.getElement('img').destroy();
    }
};

var getUsersFromBounds = function ()
{
    hideTowns();
 bounds = map.getBounds();
 neLat   = bounds.getNorthEast().lat();
 neLng   = bounds.getNorthEast().lng();
 swLat   = bounds.getSouthWest().lat();
 swLng   = bounds.getSouthWest().lng();
 r = new Request.JSON({
     'url':      responder,
     'link':     'cancel',
     onRequest:  function()
         {
             loadingImage();
             clearOutOfBoundsUserMarkers(neLat,neLng,swLat,swLng);
         },
     onComplete: function (response)
         {
             destroyLoadingImage();
                if(response.users)
                {
                 response.users.each(
                     function (user)
                     {
                         addUserMarker(user);
                     }
                 );
                }
         }
 }).get({
     'action':   'getUsers',
     'swLat':    swLat,
     'swLng':    swLng,
     'neLat':    neLat,
     'neLng':    neLng
 });
};

var getTownsFromBounds = function ()
{
    hideRegions();
    showTowns();
    
    if(activeInfoWindow)
    {
        map.removeOverlay(activeInfoWindow);
    }
    
    bounds = map.getBounds();
    r = new Request.JSON({
        'url':      responder,
        'link':     'cancel',
        onRequest:  function ()
        {
            loadingImage();
        },
        onComplete: function (response)
        {
            destroyLoadingImage();
            if(response.towns)
            {
                response.towns.each(
                function (town)
                    {
                        addTownMarker(town);
                    }
                );
            }
        }
    }).get({
        'action':   'getTowns',
        'swLat':    bounds.getSouthWest().lat(),
        'swLng':    bounds.getSouthWest().lng(),
        'neLat':    bounds.getNorthEast().lat(),
        'neLng':    bounds.getNorthEast().lng()
    });
};

var addUserMarker = function (user)
{
    if(!userMarkers[user.screenName])
    {
        point = new GLatLng(user.latitude,user.longitude);

        myIcon = new GIcon(iconPreset);
        if(user.screenName == 'gordonramsay')
        {
        myIcon.image = '/images/gordon-marker.png';
        }
        userMarkers[user.screenName] = new GMarker(point, {icon : myIcon});

    GEvent.addListener(userMarkers[user.screenName], "click", function()
    {
    triggerInfoWindow(user);
    });
    map.addOverlay(userMarkers[user.screenName]);
    return userMarkers[user.screenName];
    }
    else
    {
    userMarkers[user.screenName].show();
    }
};

var triggerInfoWindow = function (user)
{
    var response = new Request.JSON({
        'url':      responder,
        'link':     'cancel',
        onRequest:  function ()
        {
            loadingImage();
        },
        onComplete: function (r)
        {
            destroyLoadingImage();
            if(r.error)
            {
               return false;
            }
            
            wrapper = new Element('div',{'class':'info-bubble'});

            wrapper.grab(
                new Element('h4',
                {
                    'class':    'screen-name',
                    'html':     user.screenName
                }
            ));
            wrapper.grab(
                new Element('img',
                   {
                       'src':      '/users/tiny/'+r.detail.profileImage,
                       'alt':      'Picture of '+user.screenName
                   }
            ));
            
            if(r.detail.status != 'false' && r.detail.status)
            {
                wrapper.grab(
                    new Element('p',
                    {
                        'class':   'status',
                        'html':    user.screenName + ' is '+r.detail.status
                    }
                ));
            }
            wrapper.grab(
               new Element('p',
               {
                   'class':    'county',
                   'html':     r.detail.area
               }
            ));
            
            links = new Element('p',
                {
                    'class':    'links'
                }
            );
            
            vpLink = new Element('a',
            {
                'href':     '/profile/'+user.screenName,
                'html':     '► View profile',
                'class':    'button'
            });

            vpLink.addEvent('click',
                function ()
                {
                    trackEvent('mapseeprofile');
                }
            );

            links.grab(vpLink);

            links.appendText(' ');

            if(user.screenName != 'gordonramsay' && token && r.addFriend === true)
            {
                addFriendLink = new Element('a',
                {
                    'href':     user.screenName, 
                    'html':     '► Add as friend',
                    'id':       'req-'+user.screenName,
                    'class':    'button'
                });
            
                addFriendLink.addEvent('click',
                    function (ev)
                    {
                        ev.preventDefault();
                        r = new Request.JSON({
                            'url':      responder,
                            'link':     'cancel',
                            onSuccess:  function (response)
                            {
                                if(response.token)
                                {
                                    token = response.token;
                                    span = new Element('span',{
                                        'html':     'Request sent',
                                        'class':    'button'
                                    }).replaces(addFriendLink);
                                    // addFriendLink.set('html','Request sent');
                                    // addFriendLink.removeEvents('click');
                                    // addFriendLink.addEvent('click',
                                    //     function (ev)
                                    //     {
                                    //         ev.preventDefault();
                                    //     }
                                    // );
                                    addRoundedCorners(span);
                                }
                            }
                        }).post({
                            'token':        token,
                            'action':       'addFriend',
                            'username':     user.screenName
                        });
                        trackEvent('mapaddfriend');
                    }
                );
                links.grab(addFriendLink);
            }
            wrapper.grab(links);
            userMarkers[user.screenName].openInfoWindow(wrapper, {maxHeight: 180, maxWidth: 220});
            GEvent.addListener(userMarkers[user.screenName], "infowindowopen", function()
             {
                    addRoundedCorners(vpLink);
                    if(user.screenName != 'gordonramsay' && token && r.addFriend === true)
                    {
                        addRoundedCorners(addFriendLink);
                    }
             });
            }
    });
    r = response.get(
        {
            'action':   'getUserDetail',
            'user':     user.screenName
        }
    );
};

var clearOutOfBoundsUserMarkers = function(neLat, neLng, swLat, swLng)
{
 x = 0;
 forEach(userMarkers, function (userMarker)
 {
     if(
         userMarker.getPoint().lat() > neLat
         || userMarker.getPoint().lng() > neLng
         || userMarker.getPoint().lat() < swLat
         || userMarker.getPoint().lng() < swLng
     ){
         userMarker.hide();
     }
     x++;
 });
};

var clearUserMarkers = function ()
{
 forEach(userMarkers, function (userMarker)
 {
     userMarker.hide();
 });
};

var addRegions = function ()
{
    hasRegions = true;
 map.clearOverlays();
 names =     new Array();
 lats =      new Array();
 lngs =      new Array();
 scores =    new Array();
 document.getElements('div#chart ol li').each(
     function (li)
     {
         names[n] =  li.getElement('a.region').get('html');
         lats[n] =   li.getElement('span.latitude').get('html');
         lngs[n] =   li.getElement('span.longitude').get('html');
         scores[n] = li.getElement('span.score').get('html');
         point = new GLatLng(lats[n],lngs[n]);
         marker = new Element('a',{
             'id':       'pos'+n,
             'class':    'region-marker',
             'href':     '#'
         });
         marker.grab(new Element('div',
             {
                 'class':        'score',
                 'html':         scores[n]
             }
         ));
         marker.grab(new Element('img',
             {
                 'src':          "/images/chef-hat.png",
                 'alt':          names[n]
             }
         ));
         regionMarkers['pos'+n] = new ELabel(
             point,
             new Element('div').grab(marker).get('html'),
             'region-marker-container',
             new GSize(-35,0)
         );
         map.addOverlay(regionMarkers['pos'+n]);
         addRegionListener($('pos'+n),names[n],scores[n],lats[n],lngs[n]);

        li.getElement('a.region').addEvent('click',
            function (ev)
            {
                ev.preventDefault();
                id = ev.target.get('rel');
                
                map.setZoom(6);
                $(id).fireEvent('click',ev);
                window.scrollTo(0,$('map').getPosition().y);
                trackEvent('leaderboard');
            
            }
        );

         n++;
     }
 );
};

var addRegionListener = function (el,name,sc,lat,lng)
{
    el.addEvent('click', function (ev)
    {
        if(activeInfoWindow)
        {
            map.removeOverlay(activeInfoWindow);
        }
        
        point = new GLatLng(lat,lng);
        ev.preventDefault();
        score = new Element('div',{'class':'score'});
        score.grab(new Element('p',
            {
                'class':        'region',
                'html':         name
            }
        ));
        score.grab(new Element('p',
            {
                'class':        'score',
                'html':         sc
            }
        ));
        activeInfoWindow = new ELabel(
            point,
            score.get('html'),
            'score-marker',
            new GSize(30,-71)
        );
        map.addOverlay(activeInfoWindow);
        map.panTo(point);
    });
};

var animateRegions = function (num)
{
    if(num >= document.getElements('div#chart ol li').length)
    {
     return false;
    }
    
    properties = new Object({
     'duration':     'long',
     'transition':   Fx.Transitions.Elastic.easeOut,
     'link':         'chain'
    });
    
    idAttr = String('pos'+String(num));
    
    if(!$(idAttr))
    {
     setTimeout('animateRegions('+ (++num) +')',200);
     return false;
    }
    
    image = $(idAttr).getElement('img');
    
        newHeight = (115 - (num * 6));
        newWidth  = newHeight * 0.61;
    
    morph = new Fx.Morph(image,properties).start(
     {
        'width':        newWidth,
        'height':       newHeight,
        'margin-top':   (115 - newHeight)
     }
    );
    setTimeout('animateRegions('+ (++num) +')',200);
};

var addTownMarker = function (town)
{
 if(!townMarkers[town.name])
 {
     point = new GLatLng(town.latitude,town.longitude);
     markerHTML = '<img src="/images/town-marker.png" width="35" height="53" alt="'+town.name+'" />';
     townMarkers[town.name] = new ELabel(point,markerHTML,'town-marker',new GSize(-12,0));
     map.addOverlay(townMarkers[town.name]);
 }
};

var hideRegions = function ()
{
    forEach(regionMarkers,
        function (regionMarker)
        {
            regionMarker.hide();
        }
    );
};

var showRegions = function ()
{
    forEach(regionMarkers,
        function (regionMarker)
        {
            regionMarker.show();
        }
    );
                     
};

var hideTowns = function ()
{
    forEach(townMarkers,
        function (townMarker)
        {
            townMarker.hide();
        }
    );
};

var showTowns = function ()
{
    forEach(townMarkers,
        function (townMarker)
        {
            townMarker.show();
        }
    );
};

var equaliseRows = function ()
{
 // Set the first row so all items are equal height
 txHeight        = $('tx-info').getSize().y;
 loginHeight     = $('login').getSize().y;
 
 if(loginHeight > txHeight)
 {
     $('tx-info').setStyle('height',loginHeight);
 }
 if(txHeight > loginHeight)
 {
     $('login').setStyle('height',txHeight -1);
 }

 // Equalise the heights of the second row
 chartHeight     = $('chart').getSize().y;
 featuredHeight  = $('cookalong-of-the-week').getSize().y;
 
 $('cookalong-of-the-week').setStyle('height',chartHeight);
};

var makeChangeStatusForm = function ()
{
    form = new Element('form',
        {
            'class':    'change-status-form',
            'method':   'get'
        }
    );
    submitEvent = form.addEvent('submit',
        function (submit)
        {
            submit.preventDefault();
            request = new Request.JSON({
             'url':      responder,
             'link':     'cancel',
             onComplete: function(response)
                 {
                    if(response.error)
                    {
                        form.removeEvents('submit');
                        return false;
                    }
                    else
                    {
                        token = response.token;
                        setStatus(response.statusMsg);
                    }
                    trackEvent('changestatusback');
                 }
         }).post({
             'action':   'updateStatus',
             'status':   !input.value ? false : input.value,
             'token':    token
         });
        }
    );
    para = new Element('p',
        {
            'html':     $('login').getElement('h3 span').get('html') + ' is...'
        }
    );
    para.grab(new Element('br'));
    input = new Element('input',
        {
            'type':     'text',
            'name':     'status',
            'maxlength':60
        }
    );
    input.addEvents({
        'blur': function (ev)
        {
            form.fireEvent('submit',ev);
        }
    });
    
    submit = new Element('input',
        {
            'type':     'submit',
            'value':    'Update',
            'class':    'button'
        }
    );

    para.grab(input);
    para.appendText(' ');
    para.grab(submit);

    form.grab(para);

    setTimeout("addRoundedCorners(submit,'beige')",10);

    return form;
};

var setStatus = function (status)
{
    if(status !== false)
    {
        para = new Element('p',
            {
                'class':    'status',
                'html':     $('login').getElement('h3 span').get('html') + ' is ' + status + ' – '
            }
        );
        trigger = new Element('a',
            {
                'html':     'Change Status',
                'href':     '#'
            }
        );
    }
    else
    {
        para = new Element('p',
            {
                'class':    'status'
            }
        );
        trigger = new Element('a',
            {
                'html':     'What are you doing now?',
                'href':     '#'
            }
        );
    }
    para.grab(trigger);
    attatchChangeStatusListener(trigger);
    para.replaces($('login').getElement('form'));
};

var attatchChangeStatusListener = function (trigger)
{
    trigger.addEvent('click',
        function (ev)
        {
            ev.preventDefault();
            form = makeChangeStatusForm();
            form.replaces(ev.target.parentNode);
            form.getElement('input').focus();
        }
    );
};

var addStatusListener = function ()
{
    if($('login').tagName == 'DIV')
    {
        attatchChangeStatusListener($('change-status'));
    }
};

var triggerGeocodeError = function ()
{
    if(!$defined($('error-message')))
    {
        errorMessage = new Element('p',{
            'class':        'intro',
            'html':         'Sorry, I couldn\'t find a match for that location. Try a broader search, like a large town near the place you\'re looking for',
            'id':           'error-message'
        });
        errorMessage.inject(document.getElement('p.intro'),'after');
    }
    errorMessage.highlight('#F91C01');
    return false;
    
};

var initGMap = function ()
{
    if(window.GBrowserIsCompatible())
 {
     window.addEvent('unload',function (){ GUnload(); });

     // Create all the elements we'll need for the Google Map
     // Starting with the fieldset, legend and intro para
     var fieldset = new Element('form',
         {
             'id':       'map-wrapper',
             'action':   '/search',
             'method':   'get'
         }
     );
     legend = new Element('h3',{ 'html':'Search the map:'});
     fieldset.grab(legend);
 
        fieldset.grab(new Element('p',{
            'class':            'intro',
            'html':             'Search for other Cookalongers on the map, by postcode, town or username. Use the dropdown to change your search option.'
        }));
        
     // Create the form elements that do the searching
     searchContainer = new Element('p',{'class':'intro' });
     searchLabel = new Element('label', {'html':'Search:&nbsp;'});
     searchInput = new Element('input',
         {
             'type':     'text',
             'name':     'term',
             'id':       'term'
         }
     );
     searchLabel.grab(searchInput);
     searchContainer.grab(searchLabel);
 
     searchSelect = new Element('select',
            {
                'name':     'action',
                'id':       'action'
            }
     );
 
     searchSelect.grab(new Element('option',
         {
             'value':    'searchByPostcode',
             'html':     'Postcode'
         }
     ));
 
     searchSelect.grab(new Element('option',
         {
             'value':    'searchByTown',
             'html':     'Town'
         }
     ));
 
     searchSelect.grab(new Element('option',
         {
             'value':    'searchByUsername',
             'html':     'Username'
         }
     ));
 
     searchContainer.grab(searchSelect);
 
     searchButton = new Element('input',
         {
             'type':     'submit',
             'name':     'searchButton',
             'id':       'search-button',
             'class':    'button search',
             'value':    '► Search'
         }
     );
     
        fieldset.addEvent('submit',
            function (ev)
            {
                if(searchSelect.value == 'searchByPostcode' || searchSelect.value == 'searchByTown')
                {
                    trackEvent('searchresults');
                    ev.preventDefault();
                    r = new Request.JSON({
                        'url':      responder,
                        'link':     'cancel',
                        onRequest:  function ()
                        {
                            loadingImage();
                        },
                        onComplete: function (response)
                        {
                            destroyLoadingImage();
                            if(response.error)
                            {
                                return triggerGeocodeError();
                            }
                            
                            if(errorMessage)
                            {
                                errorMessage.destroy();
                                errorMessage = false;
                            }
                            
                            if(searchSelect.value == 'searchByPostcode')
                            {
                                point = new GLatLng(response.latitude,response.longitude);
                                map.setCenter(point,14);
                            }
                            else
                            {
                                if(response.google)
                                {
                                    point = new GLatLng(response.latitude,response.longitude);
                                    map.setCenter(point,11);
                                }
                                else
                                {
                                    bounds = new GLatLngBounds(
                                        new GLatLng(response.swLat,response.swLng),
                                        new GLatLng(response.neLat,response.neLng)
                                    );
                                    zoomLevel = map.getBoundsZoomLevel(bounds);
                                    zoomLevel = zoomLevel > 11 ? 11 : zoomLevel;
                                    
                                    map.setCenter(
                                        new GLatLng(response.cLat,response.cLng,zoomLevel)
                                    );
                                }
                            }
                        }
                    }).get({
                        'action':   searchSelect.value,
                        'term':     searchInput.value
                    });
                }
            }
        );

     searchContainer.grab(searchButton);
     fieldset.grab(searchContainer);

     // Zoom controls
     zoomIn = new Element('input',
         {
             'type':     'submit',
             'name':     'zoomin',
             'value':    '+ Zoom',
             'class':    'button'
         }
     );
 
     zoomOut = new Element('input',
         {
             'type':     'submit',
             'name':     'zoomout',
             'value':    '- Zoom',
             'class':    'button'
         }
     );

     zoomControls = new Element('span',{'class':'zoom-container'});
     zoomControls.grab(zoomIn,'bottom');
     zoomControls.appendText(' ');
     zoomControls.grab(zoomOut,'bottom');
 
     searchContainer.grab(zoomControls,'top');
 
     // Map Div
     mapDiv = new Element('div',{'id':'map'});
     mapDiv.setStyle('display','block');
     fieldset.grab(mapDiv);
 
     // Build the Google Map
     map = new GMap2(mapDiv);
     map.setCenter(new GLatLng(54.648413,-4.921875),6);
     map.enableContinuousZoom();
 
     zoomIn.addEvent('click',
         function (ev)
         {
             ev.preventDefault();
             map.zoomIn();
         }
     );
 
     zoomOut.addEvent('click',
         function (ev)
         {
             ev.preventDefault();
             map.zoomOut();
         }
     );

     // Hidden latitude/longitude elements
     lat = new Element('input',
         {
             'type':     'hidden',
             'name':     'latitude',
             'id':       'latitude'
         }
     );
     lng = new Element('input',
         {
             'type':     'hidden',
             'name':     'longitude',
             'id':       'longitude'
         }
     );
     fieldset.grab(lat);
     fieldset.grab(lng);

     // Insert the stuff we just created in to the DOM, replacing the placeholder
     fieldset.replaces($('map-placeholder'));
     map.checkResize();
     map.setCenter(new GLatLng(54.648413,-4.921875),6);
     geocoder = new GClientGeocoder();
 
     GEvent.addListener(map,'moveend',
         function ()
         {
             if(map.getZoom() >= 11)
             {
                 getUsersFromBounds();
             }
             else if(map.getZoom() >= 8 )
             {
                 clearUserMarkers();
                 getTownsFromBounds();
             }
             else
             {
                    showRegions();
                    hideTowns();
             }
         }
     );
 
 } // end if browser is compatible
};

var highlightUser = function ()
{
    if($defined($('highlight')))
    {
        u = $('highlight');
        if(Number(u.getElement('span.latitude').get('html')) == 0)
        {
            return false;
        }

        lat = u.getElement('span.latitude').get('html');
        lng = u.getElement('span.longitude').get('html');

        user = new Object({
           'screenName':    u.getElement('span.username').get('html'),
           'latitude':      lat,
           'longitude':     lng
        });

        addUserMarker(user);
        triggerInfoWindow(user);
        map.setCenter(new GLatLng(lat,lng),17);
        window.scrollTo(0,$('map').getPosition().y);
    }
};

window.addEvents({
    'domready' : function ()
     {
            addStatusListener();
            initGMap();
         addRegions();
            equaliseRows();
            addRedArrow();
            roundCorners();
            highlightUser();
     },
    'load' : function ()
     {
         setTimeout('animateRegions(0)',1000);
     }
});