/*
 * Enchance elements' prototypes
 */
Event.observe(document, 'dom:loaded', function()
{
    // define common vars
    var URL =
    {
        'validate'  : '/validate',
        'message'   : '/message'
    };

    // Extend Object
    Object.extend(Object,
    {
        isObject: function(object)
        {
            return (typeof object == 'object');
        }
    });

    // Add custom methods to Element class
    Element.addMethods(
    {
        // setStatus Ð set given status as css class
        'setStatus': function(element, status)
        {
            element = $(element);

            $w(element.className).each(function(classItem)
            {
                if (classItem.match(/^status-/))
                {
                    element.removeClassName(classItem);
                }
            });

            element.addClassName('status-' + status);
        },

        // clearStatus Ð removes given status as css class
        'clearStatus': function(element, status)
        {
            element = $(element);

            element.removeClassName('status-' + status);
        },

        // getStatus Ð returns current status from css class
        'getStatus': function(element)
        {
            element = $(element);

            $w(element.className).each(function(classItem)
            {
                if (classItem.match(/^status-/))
                {
                    return classItem.replace(/^status-/, '');
                }
            });
        },

        // validate
        'validate': function(element)
        {
            element = $(element);

            switch (element.tagName)
            {
                case 'INPUT':
                case 'TEXTAREA':

                    var parameters = {};

                    parameters[element.name] = element.value;

                    if (element.value.length > 0)
                    {
                        requestData(URL['validate'], parameters, function(data)
                        {
                            // replace given text with parsed one
                            element.value = data[element.name]['parsed'];

                            // set given status
                            element.setStatus(data[element.name]['status']);

                            // get errorId
                            var errorId = element.retrieve('errorId', 0);

                            if (data[element.name]['error'])
                            {
                                var errorId = Errors.push(data[element.name]['error'], errorId);

                                // store new errorId
                                element.store('errorId', errorId);
                            }
                            else
                            { 
                                if (errorId)
                                {
                                    // remove error from the page
                                    Errors.pop(errorId);

                                    // clear errorId
                                    element.store('errorId', 0);
                                }
                            }
                        });
                    }
                    else
                    {
                        element.setStatus('empty');

                        // get errorId
                        var errorId = element.retrieve('errorId', 0);

                        if (errorId)
                        {
                            // remove error from the page
                            Errors.pop(errorId);

                            // clear errorId
                            element.store('errorId', 0);
                        }
                    }

                    break;

                default:
                    // do nothing
            }
        },

        'getPositions': function(element)
        {
            element = $(element);

            // TODO: Make it general
            var left    = parseInt(Element.getStyle(element, 'left'), 10)     || 0;
            var top     = parseInt(Element.getStyle(element, 'top'), 10)      || 0;
            var right   = parseInt(Element.getStyle(element, 'right'), 10)    || 0;
            var bottom  = parseInt(Element.getStyle(element, 'bottom'), 10)   || 0;

            return {'left': left, 'top': top, 'right': right, 'bottom': bottom};
        }
    });

    // hide errors div on load
    if ($('errors'))
    {
        $('errors').hide();
    }

    Errors =
    {
        'init': function(target)
        {
                this.target = target;
        },

        // push new error message to the messages array
        // TODO: Make it as real array with representation in #errors div
        // TODO: Make it to pull error message text from db by given message handler
        'push': function(text, messageId)
        {
            // get text
            if (text.indexOf(' ') < 1)
            {
                var errors = $(document.body).retrieve('errors', []);

                if (errors[text])
                {
                    // Call itself again with new data
                    Errors.push(errors[text], messageId);
                }
                else
                {
                    requestData(URL['message'], {'message': text}, function(data)
                    {
                        // get errors array
                        var errors = $(document.body).retrieve('errors', []);

                        // store fetched message
                        errors[data['key']] = data['message'];

                        // put it back to the docuemnt
                        $(document.body).store('errors', errors);

                        // Call itself again with new data
                        Errors.push(data['message'], messageId);
                    });
                }
            }
            else
            {
                if (this.target)
                {
                    if (!(this.target.down('ul')))
                    {
                        this.target.insert({'bottom': new Element('ul')});
                    }
    
                    // remove old message if we have one
                    if (messageId && $(messageId))
                    {
                        $(messageId).remove();
                    }
                    else
                    {
                        var messageId = 'error_' + Math.floor(Math.random()*999);
                    }
    
                    this.target.down('ul').insert({top: new Element('li', {'id': messageId}).update(text)});
    
                    if (!$('errors').visible())
                    {
                        Effect.BlindDown('errors');
                    }
    
                    return messageId;
                }
                else
                {
                    alert(text);
                }
            }

            return messageId;
        },

        // pop error message by given id
        'pop': function(messageId)
        {
            var text;
            // remove old message if we have one
            if (messageId && $(messageId))
            {
                text = $(messageId).innerHTML;

                $(messageId).remove();
            }

            return text;
        }
    };

/* Ajax wrapper */

    // TODO: Make it as part of the framework
    window.requestData = function(url, params, callback)
    {
        var token;
    
        if (token = readCookie('session'))
        {
            params = $H(params).merge({"token": token});
        }
    
        new Ajax.Request(url+'.json',
        {
            'method': 'post',
            'parameters': params,
            'requestHeaders': {'Accept': 'application/json'},
            'onSuccess': function(transport)
            {
                // eval received json
                var jsonData = transport.responseText.evalJSON(true);
                callback(jsonData);
            }
        });
    }

/* pretty looking alert */

    // TODO: Make it as part of the framework
    window.oAlert = window.alert;

    window.alert = function(message)
    {
        if (isSet('IA') && IA.alert)
        {
            IA.alert(message);
        }
        else
        {
            oAlert(message);
        }

        return true;
    }

// done with library load
// let others to do their job

    Event.fire(document, 'core:loaded');

});

/*
 * Common functions
 */

function isSet(v)
{
    if (typeof window[v] != "undefined")
    {
        return true;
    }

    return false;
}

/* from: http://www.quirksmode.org/js/cookies.html */

function createCookie(name, value, days)
{
    if (days)
    {
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        var expires = "; expires="+date.toGMTString();
    }
    else
    {
        var expires = "";
    }

    document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name)
{
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');

    for (var i=0;i < ca.length;i++)
    {
        var c = ca[i];

        while (c.charAt(0)==' ')
        {
            c = c.substring(1,c.length);
        }

        if (c.indexOf(nameEQ) == 0)
        {
            return c.substring(nameEQ.length,c.length);
        }
    }

    return null;
}

function eraseCookie(name)
{
    createCookie(name, "", -1);
}

// Based on http://awardwinningfjords.com/2009/07/22/google-maps-with-jquery.html
function googleMap(element, address, options)
{
    element = $(element);

    var defaults =
    {
        'lat':  43.668803082531305,
        'long': -79.39051199999999,
        'zoom': 16,
        'mapTypeId': google.maps.MapTypeId.ROADMAP,
        'disableDefaultUI': true,
        'navigationControl': true,
        'navigationControlOptions': {'style': google.maps.NavigationControlStyle.SMALL},
        'scaleControl': false,
        'scrollwheel': false
    };

    options         = Object.extend(defaults, options || {});

    var center      = new google.maps.LatLng(options.lat, options.long);
    var map         = new google.maps.Map(element, Object.extend(options, {'center': center}));

    // store default location
    map.defaultLocation = center;

    var geocoder    = new google.maps.Geocoder();

    geocoder.geocode({ 'address': address }, function(results, status)
    {
        if (status == google.maps.GeocoderStatus.OK && results.length)
        {
            if (status != google.maps.GeocoderStatus.ZERO_RESULTS)
            {
                map.set_center(results[0].geometry.location);

                map.defaultLocation = map.getCenter();

                var marker = new google.maps.Marker(
                {
                    'position': map.getCenter(),
                    'map': map
                });
            }
        }
    });

    return map;
}

function googleMapShowRoute(map, from, panel)
{
    if (typeof directionsService == 'undefined')
    {
        directionsService = new google.maps.DirectionsService();
    }
    if (typeof directionsDisplay == 'undefined')
    {
        directionsDisplay = new google.maps.DirectionsRenderer();
    }

    // show panel if so
    if (panel)
    {
        panel = $(panel);
        directionsDisplay.setPanel(panel);
    }

    directionsDisplay.setMap(map);

    var request =
    {
        'origin': from, 
        'destination': map.defaultLocation,
        'travelMode': google.maps.DirectionsTravelMode.DRIVING
    };

    directionsService.route(request, function(response, status)
    {
        if (status == google.maps.DirectionsStatus.OK)
        {
            directionsDisplay.setDirections(response);
        }
    });
}
