/*
 * /a/lib.js
 */
Event.observe(document, 'dom:loaded', function()
{
    var addGallery = function(el, handle)
    {
        new Ajax.Request('/hybridity/gallery.php',
        {
            parameters: {'handle': handle},
            onSuccess: function(transport)
            {
                el.insert(transport.responseText);
            }
        });

    }

    // content specific stuff
    // TODO: make it more generic
    Event.observe(document, 'ia:activate', function(e)
    {
        var context = Event.element(e);

        // process gallery
        context.select('.gallery').each(function(el)
        {
            if (el.hasClassName('ia_gallery'))
            {
                addGallery(el, 'gallery');
            }

            if (el.hasClassName('ia_hibridity'))
            {
                addGallery(el, 'hibridity');
            }
        });

        // add hover effect
        $$('.hoverable').each(function(el)
        {
            // mouse over
            el.observe('mouseover', function(e)
            {
                var el = Event.element(e);
    
                el.addClassName('hover');
    
                el.ancestors().find(function(el)
                {
                    el.addClassName('hover');
    
                    if (el == this)
                    {
                        return true;
                    }
                }.bind(this));
    
            }.bind(el));
    
            // mouse out
            el.observe('mouseout', function(e)
            {
                var el = Event.element(e);
    
                el.removeClassName('hover');
    
                el.ancestors().find(function(el)
                {
                    el.removeClassName('hover');
    
                    if (el == this)
                    {
                        return true;
                    }
                }.bind(this));
            }.bind(el));
        });

        context.store('active', true);
    });

    // Add custom methods
    Element.addMethods(
    {
        // Scroll element to the given one
        'scrollElementTo': function(element, element_to)
        {
            element     = $(element);
            element_to  = $(element_to);

            var pos = Element.cumulativeOffset(element_to);

            element.scrollTo(pos[0], pos[1]);

            return element;
        },

        // Move to
        'moveTo': function(element, params)
        {
            element     = $(element);

            new Effect.Move(element, params);

            return element;
        }

    });

    // canvas update on viewport resize
    canvasUpdate = function()
    {
        var current, posX, posY, currentPosX, currentPosY;

        var matrix = new Array();

        var canvasSizeX = 0;
        var canvasSizeY = 0;

        var viewSize = document.viewport.getDimensions();

        $('canvas').getElementsBySelector('.page').each(function(el)
        {
            // {{{ store original positions
            posX = el.retrieve('posX', 0);
            if (!posX)
            {
                posX = Math.round(el.positionedOffset()[0] / viewSize.width);
                el.store('posX', posX);
            }

            posY = el.retrieve('posY', 0);
            if (!posY)
            {
                posY = Math.round(el.positionedOffset()[1] / viewSize.height);
                el.store('posY', posY);
            }
            // }}}

            // make two-dimensional array
            if (!matrix[posX])
            {
                matrix[posX] = new Array();
            }
            // store positions in the matrix, assume all elements have id
            matrix[posX][posY] = el.id;

            el.setStyle(
            {
                width: viewSize.width + 'px',
                height: viewSize.height + 'px',
                left: (viewSize.width * posX) + 'px' ,
                top: (viewSize.height * posY) + 'px'
            });

            if (canvasSizeX < (viewSize.width * (posX + 1)))
            {
                canvasSizeX = (viewSize.width * (posX + 1));
            }

            if (canvasSizeY < (viewSize.height * (posY + 1)))
            {
                canvasSizeY = (viewSize.height * (posY + 1));
            }
        });

        // store matrix in the canvas
        $('canvas').store('matrix', matrix);

        // get current page, by default it's splash page
        current = $('canvas').retrieve('current', 'splash');

        // we assume that we have that data already
        currentPosX = $(current).retrieve('posX');
        currentPosY = $(current).retrieve('posY');

        // reset canvas
        $('canvas').setStyle(
        {
            width: canvasSizeX + 'px',
            height: canvasSizeY + 'px',
            left: ((viewSize.width * currentPosX) * -1) + 'px',
            top: ((viewSize.height * currentPosY) * -1) + 'px'
        });
    }

    changePage = function(page)
    {
        var posX, posY;

        // check the page
        if (!$(page))
        {
            return false;
        }

        var old = $('canvas').retrieve('current', false);

        var canvas = $('canvas').retrieve('canvas', false);

        if (page != old && canvas)
        {
            if (page == 'splash')
            {
                canvas.options.constraint = 'vertical';
            }
            else if (page == 'main')
            {
                canvas.options.constraint = 'ordinal';
            }
            else
            {
                canvas.options.constraint = 'horizontal';
            }
        }

        var viewSize = document.viewport.getDimensions();

        // we assume that we have that data already
        posX = $(page).retrieve('posX');
        posY = $(page).retrieve('posY');

        // preload content
        if ($(page).down('.content') && $(page).down('.content').hasClassName('waiting'))
        {
            new Ajax.Request('/hybridity/'+page+'.php',
            {
                onSuccess: function(transport)
                {
                    $(page).down('.content').update(transport.responseText);
                    $(page).down('.content').removeClassName('waiting');

                    // add IE hack
                    if (Prototype.Browser.IE)
                    {
                        $(page).down('.content').insert({bottom: new Element('div', {'class': 'ih_spacer'})});
                    }

                    // fix scrollbar
                    var scrollbar = $(page).retrieve('scrollbar', false);
                    if (scrollbar)
                    {
                        scrollbar.recalculateLayout();
                    }

                    // activate
                    $(page).fire('ia:activate');
                }
            });

            // get form
            if (page == 'call_for_papers')
            {
                new Ajax.Request('/hybridity/apply.php',
                {
                    onSuccess: function(transport)
                    {
                        $(page).down('.header').insert(transport.responseText);
                    }
                });
            }

            // get weather
            if (page == 'city')
            {
                new Ajax.Request('/hybridity/weather.php',
                {
                    onSuccess: function(transport)
                    {
                        $(page).down('.header').insert(transport.responseText);
                    }
                });
            }
        }
        else if (!($(page).retrieve('active', false)))
        {
            // activate
            $(page).fire('ia:activate');
        }

        // move canvas
        var beingMoved = new Effect.Move('canvas',
        {
            mode: 'absolute',
            x: (viewSize.width * posX) * -1,
            y: (viewSize.height * posY) * -1,

            // clean up after itself
            afterFinish: function()
            {
                $('canvas').store('being_moved', false);
            }
        });

        // store effect
        $('canvas').store('being_moved', beingMoved);

        // unmark previous page menu item
        if (old && $('menu_content').down('.action.page_'+old) && $('menu_content').down('.action.page_'+old).up('li'))
        {
            $('menu_content').down('.action.page_'+old).up('li').removeClassName('current');
        }

        // mark menu element as current
        if ($('menu_content').down('.action.page_'+page) && $('menu_content').down('.action.page_'+page).up('li'))
        {
            $('menu_content').down('.action.page_'+page).up('li').addClassName('current');
        }

        // store active page
        $('canvas').store('current', page);
    }

    backObserve = function(e, handler)
    {
        // add some fancy
        $$(this.tagName+'.'+$w(this.className).toArray().join('.')).invoke('removeClassName', 'hover');

        this.removeClassName('hover');
        this.stopObserving('mouseout', handler);
    }

    // {{{ Add 'ordinal' type of dragging to the Draggable class
    Draggable.addMethods(
    {
        draw: function(point) {
            var pos = this.element.cumulativeOffset();
            if(this.options.ghosting) {
                var r       = Position.realOffset(this.element);
                pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
            }

            var d = this.currentDelta();
            pos[0] -= d[0]; pos[1] -= d[1];

            if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
                pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
                pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
            }

            var p = [0,1].map(function(i){
                return (point[i]-pos[i]-this.offset[i])
            }.bind(this));

            if(this.options.snap) {
                if(Object.isFunction(this.options.snap)) {
                    p = this.options.snap(p[0],p[1],this);
                } else {
                if(Object.isArray(this.options.snap)) {
                    p = p.map( function(v, i) {
                        return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this));
                } else {
                    p = p.map( function(v) {
                        return (v/this.options.snap).round()*this.options.snap }.bind(this));
                }
            }}
/* original
            var style = this.element.style;
            if((!this.options.constraint) || (this.options.constraint=='horizontal'))
                style.left = p[0] + "px";
            if((!this.options.constraint) || (this.options.constraint=='vertical'))
                style.top    = p[1] + "px";
end of original */

/* my version */

            var style = this.element.style;

            if (this.options.constraint != 'ordinal')
            {
                if((!this.options.constraint) || (this.options.constraint=='horizontal'))
                    style.left = p[0] + "px";
                if((!this.options.constraint) || (this.options.constraint=='vertical'))
                    style.top    = p[1] + "px";
            }
            else
            {
                // check if it's mostly horizontal or vertical movement
                if (Math.abs(this.posOriginal[0] - p[0]) < Math.abs(this.posOriginal[1] - p[1]))
                {
                    // vertical drag
                    style.left  = this.posOriginal[0] + "px"; // set X to original one
                    style.top   = p[1] + "px";
                }
                else
                {
                    // horizontal drag
                    style.left  = p[0] + "px";
                    style.top   = this.posOriginal[1] + "px"; // set Y to original one
                }
            }
/* end of my version */
            if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
        }

    });
    // }}} End of Draggable class modification

    // done with library load
    // let others to do their job
    Event.fire(document, 'loaded:lib');
});

/*
 * 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);

    // {{{ prevent map from dragging along with the page
    element.up().observe('mousedown', function(e)
    {
        Event.stop(e);
    });
    // }}}

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

    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();

    bounds = new google.maps.LatLngBounds(new google.maps.LatLng(43.458297,-79.639219), new google.maps.LatLng(43.855458,-79.002481));

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

                map.defaultLocation = map.getCenter();

                if (options.showMarker)
                {
                    var marker = new google.maps.Marker(
                    {
                        'position': map.getCenter(),
                        'icon': options.marker.icon || null,
                        'shadow': options.marker.shadow || null,
                        'map': map
                    });
                }
            }
        }
    });

    // check street view
    if (options.streetview)
    {
        panorama = map.getStreetView();

        if (options.streetview.position)
        {
            panorama.setPosition(options.streetview.position);
        }

        panorama.setPov(
        {
          heading: options.streetview.heading || 0,
          zoom: options.streetview.zoom || 1,
          pitch: options.streetview.pitch || 0
        });

        if (options.streetview.visible)
        {
            panorama.setVisible(true);
        }
    }

    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 geocoder    = new google.maps.Geocoder();

    bounds = new google.maps.LatLngBounds(new google.maps.LatLng(43.3884577624356, -79.77880020141606), new google.maps.LatLng(44.04157565564786, -79.07018203735356));

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

            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);
                }
            });
        }
        else
        {
            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);
                }
                else
                {
                    var request =
                    {
                        'origin': from + ', Toronto, Canada', 
                        'destination': map.defaultLocation,
                        'travelMode': google.maps.DirectionsTravelMode.DRIVING
                    };
                
                    directionsService.route(request, function(response, status)
                    {
                        if (status == google.maps.DirectionsStatus.OK)
                        {
                            directionsDisplay.setDirections(response);
                        }
                        else
                        {
                            alert('Unable to find entred location.\n\nPlease refine your search string.');
                        }
                    });

                }
            });
        }
    });

}

function inArea(coords, offset, dims)
{
    if (offset.left < coords.x
        && coords.x < offset.left + dims.width
        && offset.top < coords.y
        && coords.y < offset.top + dims.height)
    {
        return true;
    }

    return false;
}

// EOF
