  /**
   * fo.js (Tobias Ouwejan, December 2007)
   *
   * This file contains common javascript functions that will be used in the 
   * website of Frans Ouwejan. The script depends on the prototype and scriptaculous libraries.
   * 
   */
    
    
    /** Configuration properties
     *
     */
    
    // file locations
    var MENU_DATA           = 'data/menu.txt';
    var PHOTO_LOC           = 'media/photos/';
    
    var INITIAL_GALLERY     = 'data/gallery_home.txt';
    
    // labels
    var SHOW_MENU_PREFIX    = 'Show ';
    var MORE_INFO_LABEL     = 'info';
    var CLOSE_INFO_PANEL    = 'x';
    var DATE_LABEL          = 'Date: ';
    var LOCATION_LABEL      = 'Location: ';
    var WEBSITE_LABEL       = 'Website: ';
    var OPEN_WEBSITE_LABEL  = 'Open the website';    
    
    
    // globals
    var currentDetailNode;
    var activeMenu
    
    // initiate the fo object
    Event.observe (window, 'load', function() {
        fo.init();
    }, false);
    
    /**
     * fo class
     * 
     * This class contains all necessary methods and properties for the
     * FO website.
     */
    var fo = {
        init:function(){
            var menuUri = MENU_DATA + '?'  + Math.floor(Math.random()*(1000));
            var galleryUri = INITIAL_GALLERY + '?'  + Math.floor(Math.random()*(1000));
            
            this.menu.load(menuUri);
            this.galleries.load(galleryUri, true);
        },
        publishFailure:function(request, exception){
            alert ('could not load request (' + exception + ')');
        }
    }
    
    fo.menu = {
        load: function(uri) {
            new Ajax.Request(uri, {
                method:'get',
                //requestHeaders: {Accept: 'application/json'},
                onSuccess: this.publish.bindAsEventListener(this),
                onFailure: fo.publishFailure
            });
            
            // set menu observers
            $('showMenu').observe('click', fo.galleries.showMenu.bindAsEventListener(fo.galleries));
        },
        publish: function(transport) {
            var json = transport.responseText.evalJSON(true);
            json.menu.reverse().each(function(item){
                this.createItem(item, $('menu'), true);
            }.bind(this));
            document.observe('click', function(){
                if (activeMenu)
                    Effect.Fade (activeMenu,{duration:0.2});
            })
        },
        createItem: function (menuItem, parent, top) {
            var menuListItem = Builder.node('li', null, menuItem.title);
            var menuList = Builder.node('ul', null, menuListItem);
            $(menuListItem).observe('click', this.openMenu);
            //menuList.observe('mouseout', this.close);
            
            if (menuItem.childs) {
                var submenuList = Builder.node('ul', {'style':'display:none;'});
                menuList.appendChild(submenuList);
                
                menuItem.childs.each(function(item){
                    new fo.menu.Item(item, submenuList);
                });
            }
            parent.insert(menuList, { position: $('galleryNavigation') });
        },
        openMenu: function(ev) {
            var elm = Event.element(ev);
            list = elm.up('ul').down('ul');
            if (list)
                Effect.toggle(list,'appear',{duration:0.3});
            if (activeMenu && activeMenu != list)
                Effect.Fade (activeMenu,{duration:0.2});
            activeMenu = list;
            Event.stop(ev)
        },
        loadItem: function() {
            
        },
        close: function() {
            Effect.Fade ($('contentPanel'),{duration:0.2, 'afterFinish':function(effect){
                effect.element.update('');
            }});
        }
    }
    
    fo.menu.Item = Class.create();
    fo.menu.Item.prototype = {
        item: null,
        initialize: function(item, parentNode) {
            this.item = item;
            var submenuListItem = Builder.node('li', null, item.title);
            $(submenuListItem).observe('click', this.open.bindAsEventListener(this) );
            
            parentNode.appendChild(submenuListItem);
        },
        open: function() {
            if (this.item.uri){
                new Ajax.Request(this.item.uri + '?' + Math.floor(Math.random()*(1000)), {
                    method:'get',
                    //requestHeaders: {Accept: 'application/json'},
                    onSuccess: this.publish.bindAsEventListener(this),
                    onFailure: fo.publishFailure
                });
                
                fo.galleries.close();
                
                var modelNode = Builder.node('span', {'id':'model', 'class': 'model'}, this.item.subject);  
                var captionNode = Builder.node('span', {'id':'caption', 'class': 'caption'}, this.item.caption);
                
                $('footer').appendChild(modelNode);
                $('footer').appendChild(captionNode);
            }
            if (this.item.gallery_uri){
                fo.galleries.load(this.item.gallery_uri);
            }
        },
        publish: function(transport) {
            $('contentPanel').show();
            $('contentPanel').update(transport.responseText);
        },
        close: function() {
            $('contentPanel').close();
        }
    }
    
    fo.galleries = {
        loadHomePage: false,
        
        load: function(uri, loadHomePage) {
            this.loadHomePage = loadHomePage;
            new Ajax.Request(uri, {
                method:'get',
                //requestHeaders: {Accept: 'application/json'},
                onSuccess: this.publish.bindAsEventListener(this),
                onFailure: fo.publishFailure
            });
        },
        close:function() {
            this.closeInfo();
            this.closePhoto();
            this.closeDetails();
            this.hideMenu(true);
        },
        publish: function(transport) {
            // reset the galleryMenu
            $('galleryMenu').setStyle({'left':0});
            var json = transport.responseText.evalJSON(true);
            if (this.loadHomePage)
                this.publishHome(json);
            else
                this.publishMenu(json);      
        },
        publishHome: function(json) {
            var randomNum = Math.round(((Math.random ()*json.gallery.galleries.length-1) + 0.5));
            var gal = json.gallery.galleries[randomNum];
            var photoIndex = 0;
            if (gal.photos.length > 1){
                photoIndex = Math.round( (Math.random() * gal.photos.length-1) + 0.5 )
            }
            new this.Photos(gal, photoIndex, true);
        },
        publishMenu: function(json) {
            
            $('galleryMenu').update('');
            
            json.gallery.galleries.each(function(gal){
                var thumb = this.createThumb(gal);
            }.bind(this));
            
            if (this.carousel) this.carousel.destroy();
            
            $$('.carousel-component').each( function(elm){
                this.carousel = new Carousel(elm,  {buttonStateHandler: buttonStateHandler, animParameters: {duration: 0.5}, animHandler: animHandler});
            }.bind(this));
            
            $('galleryMenuTitle').update(json.gallery.title);
            $('showMenu').update(SHOW_MENU_PREFIX + json.gallery.title);
            //$('showMenu').observe('click', this.showMenu.bindAsEventListener(this));
            
            $('showMenu').show();
            
            this.showMenu()
        },
        
        createThumb: function(gal) {
            var thumb = Builder.node('li', {'style':'background-image:url(' + PHOTO_LOC + gal.thumbnail + ')'});
            $(thumb).addClassName('thumb');
            $('galleryMenu').appendChild(thumb);
            
            thumb.observe('click', function(ev){
                fo.galleries.publishPhotos(gal);
                this.hideMenu();
            }.bind(this));
            return this;
        },
        
        hideMenu: function(clean) {
            buttonStateHandler($('previousSlide'), false)
            buttonStateHandler($('nextSlide'), false)
            $('showMenu').removeClassName('hide');
            //$('hideMenu').addClassName('hide');
            
            if ( !$('galleryMenuPanel').visible() ) 
                return;
            
            Effect.BlindUp($('galleryMenuPanel'), {'duration':0.5});
            
            $('galleryMenuNavigation').hide();
            
            if (clean) $('showMenu').update('');
        },
        showMenu: function() {
            
            buttonStateHandler($('previousSlide'), this.carousel.currentIndex != 0)
            buttonStateHandler($('nextSlide'), this.carousel.options.size > this.carousel.options.numVisible)
            $('showMenu').addClassName('hide');
            
            if ( $('galleryMenuPanel').visible() ) 
                return;
            
            Effect.BlindDown($('galleryMenuPanel'), {'duration':0.5, scaleContent:false, keepBackgroundImage:true});
            
            $('galleryMenuNavigation').show();
        },
        
        publishPhotos: function(gal, photoIndex) {
            var photoIndex = photoIndex || 0;
            var photo = gal.photos[photoIndex];
            
            var modelNode = Builder.node('span', {'id':'model', 'class': 'model'}, gal.model);
            var captionNode = Builder.node('span', {'id':'caption', 'class': 'caption'});
            var photoLinkPanel = Builder.node('span', {id: 'photoMenu', className:'photo-links-panel'});
            var infoNode = Builder.node('span', {'class':'info'}, MORE_INFO_LABEL);
            $(infoNode).observe('click', function(){
                this.publishInfo(gal);
            }.bind(this));
            
            $('footer').update(infoNode);
            $('footer').appendChild(photoLinkPanel);
            $('footer').appendChild(modelNode);
            $('footer').appendChild(captionNode);
            
            new this.Photos(gal);
        },
        
        publishInfo: function(gal) {
            if ($('infoPanel')) {
                new Effect.Highlight($('infoPanel'), {duration: 0.4, startcolor:'#cfced3', endcolor:'#e77817'});
                return;
            }
            var infoNodes = [];
            var closeButton = Builder.node('div', {'class':'close-button'}, CLOSE_INFO_PANEL);
            $(closeButton).observe('click', this.closeInfo);
            infoNodes.push(closeButton)
            
            if (gal.location)
                infoNodes.push(Builder.node('div', null, LOCATION_LABEL + gal.location));
            if (gal.date)
                infoNodes.push(Builder.node('div', null, DATE_LABEL + gal.date));
            if (gal.website) {
                infoNodes.push(Builder.node('span', null, WEBSITE_LABEL));
                infoNodes.push(Builder.node('a', {'href': gal.website, 'target': '_blank'}, OPEN_WEBSITE_LABEL));
            }
            var infoPanel = $(Builder.node('div', {'id':'infoPanel', 'class': 'info-panel', 'style':'display:none'}, infoNodes));
            $('photoPanel').appendChild(infoPanel);
            Effect.Appear(infoPanel, {to:0.6})
            
            this.hideMenu();
        },
        closeInfo: function() {
            if ($('infoPanel')) {
                Effect.Fade($('infoPanel'), {'duration':0.2, 'afterFinish':function(effect){
                    effect.element.remove();
                }});
            }
        },
        closePhoto:function() {
            if (currentDetailNode) {
                Effect.Fade(currentDetailNode, {'duration':0.5, 'afterFinish':function(effect){
                    effect.element.remove();
                }});
                currentDetailNode = null;
            }
        },        
        closeDetails:function() {
                        
            $('footer').update('');

        }
    }
    
    
    fo.galleries.Photos = Class.create();
    fo.galleries.Photos.prototype = {
        gallery:null,
        
        initialize: function(gal, photoIndex, ignoreFooter) {
            this.gallery = gal;
            this.index = photoIndex || 0;
            //this.sibling = sibling;
            
            this.firstView = true;
            this.publish(ignoreFooter);
        },
        previous: function() {
            this.index--;
            this.firstView = false;
            fo.galleries.hideMenu();
            fo.galleries.closeInfo();
            this.publish(false, true);
        },
        next: function() {
            if ( (this.index + 1 ) >= this.gallery.photos.length) return;
            this.index++;
            this.firstView = false;
            fo.galleries.hideMenu();
            fo.galleries.closeInfo();
            this.publish(false, true);
        },     
        publish: function(ignoreFooter, ignoreInfo) {
            
            fo.menu.close();
            
            this.photo = this.gallery.photos[this.index];
            
            var detailNode = Builder.node('img', {'src': '' + PHOTO_LOC + this.photo.src, 'style':'display:none' });
            var photoNode = Builder.node('div', {'class':'photo'}, detailNode);
            
            $('photoPanel').appendChild(photoNode)
            //alert (photoNode)
            if (!ignoreFooter) // bad decision maker...
                $(photoNode).observe('click', fo.galleries.showMenu.bindAsEventListener(fo.galleries))
            
            Effect.Appear(detailNode);
            
            if (!ignoreFooter)
                this.updateFooter(ignoreInfo);
            
            fo.galleries.closePhoto();
            currentDetailNode = photoNode;
        },
        updateFooter: function(ignoreInfo){
            if ($('caption'))
                $('caption').update(this.photo.caption);
            if ($('model')) {
                if (this.photo.model)
                    $('model').update(this.photo.model);
                else
                    $('model').update(this.gallery.model);
            }
            
            if (!ignoreInfo)
                fo.galleries.closeInfo();
            this.createNavigation();
        },
        createNavigation: function() {
            if (this.gallery.photos.length > 1) {
                
                
                var numOfPhotos = Builder.node('span', {'class': 'photo-index'}, this.index+1 + '|' + this.gallery.photos.length);
                
                previousCls = (this.index > 0) ? 'previous' : 'previous disabled';
                nextCls = (this.index < this.gallery.photos.length-1) ? 'next' : 'next disabled';
                var nextButton = $(Builder.node('div', {className:nextCls}, '.'));
                var previousButton = $(Builder.node('div', {className:previousCls}, '.'));
                
                if (this.index < this.gallery.photos.length)
                    nextButton.observe('click', this.next.bindAsEventListener(this));
                if (this.index > 0)
                    previousButton.observe('click', this.previous.bindAsEventListener(this));
                var photoLinkPanel = Builder.node('span', {'class':'photo-links-panel'}, [previousButton, numOfPhotos, nextButton]);
                $('photoMenu').update('');
                $('photoMenu').insert(photoLinkPanel, $('info'));
                previousButton.update('&nbsp;');
                nextButton.update('&nbsp;');
                
                if (this.firstView)
                    Effect.Pulsate(photoLinkPanel, {duration: 3, from: 0.2, pulses: 2});
            }
            
        }
        
    }
    