
(function(){

    var Dom = YAHOO.util.Dom;
    var Event = YAHOO.util.Event;
    var CustomEvent = YAHOO.util.CustomEvent;
    var Selector = YAHOO.util.Selector;
    
    var IMG = '/site_media/capdigital/img';
    
    // no console fallback
    if (typeof console == 'undefined' || YAHOO.env.ua.webkit) {
        ConsoleObj = function(){
        };
        ConsoleObj.prototype = {
            debug: function(){
            },
            info: function(){
            },
            warn: function(){
            },
            error: function(){
            },
            trace: function(){
            }
        }
        console = new ConsoleObj();
    };
    
    var updateMenu = function(menuNode, pageName){
        //console.info('updateMenu: ', menuNode, pageName);
        var i, q;
        
        q = Selector.query('div[class*=active]', menuNode);
        for (var i in q) 
            YAHOO.util.Dom.removeClass(q[i], 'active');
        
        q = Selector.query('div[class=' + pageName + ']', menuNode);
        if (!q.length) {
            //console.warn('updateMenu: no such menu: ' + pageName);
            return;
        }
        
        YAHOO.util.Dom.addClass(q[0], 'active');
    };
    
    /**
     * CapAnim
     */
    var CapAnim = function(){
    };
    CapAnim.prototype = {
        open: function(){
            console.debug(this + ': open()');
        },
        close: function(){
            console.debug(this + ': close()');
        },
        
        toString: function(){
            return 'CapAnim';
        }
    };
    
    /**
     * CapAnimDoors
     */
    var CapAnimDoors = function(){
    };
    YAHOO.extend(CapAnimDoors, CapAnim, {
    
        open: function(){
            CapAnimDoors.superclass.open.call(this);
            return this._animDoors(true);
        },
        
        close: function(){
            CapAnimDoors.superclass.close.call(this);
            return this._animDoors(false);
        },
        
        _animDoors: function(animOpen){
            console.info(this + ': openDoors', arguments);
            
            var event = CustomEvent('animateDoors');
            
            var leftDoor = Dom.get('left-door');
            var rightDoor = Dom.get('right-door');
            
            var leftAnim = new YAHOO.util.Anim(leftDoor, {
                left: {
                    to: animOpen ? -297 : 78
                }
            }, 0.8, YAHOO.util.Easing.easeOut);
            var rightAnim = new YAHOO.util.Anim('right-door', {
                left: {
                    to: animOpen ? 24 : -352
                }
            }, 0.8, YAHOO.util.Easing.easeOut);
            
            leftAnim.animate();
            rightAnim.animate();
            
            return leftAnim.onComplete;
        },
        
        toString: function(){
            return 'CapAnimDoors';
        }
        
    });
    
    /**
     * CapAnimFade
     */
    var CapAnimFade = function(){
    };
    YAHOO.extend(CapAnimFade, CapAnim, {
        open: function(){
            CapAnimDoors.superclass.open.call(this);
            return this._fade(true);
        },
        
        close: function(){
            CapAnimDoors.superclass.close.call(this);
            return this._fade(false);
        },
        
        _fade: function(fadeIn){
        
            var effect = {
                opacity: {
                    to: fadeIn ? 1.0 : 0.0
                }
            };
            
            var anim = new YAHOO.util.Anim('content', effect, 0.5, YAHOO.util.Easing.easeOut);
            
            setTimeout(function(){
                anim.animate();
            }, 1);
            
            return anim.onComplete;
        }
        
    });
    
    
    /**
     * CapSite
     */
    var CapSite = function(){
    
        console.info(this + ': constructor', arguments);
        
        this.initLayout();
        this.initEvents();
        
        this._pageMap = {
            'intro': CapPageIntro,
            'profile': CapPageProfile,
            'print': CapPagePrint,
            'internet': CapPageInternet,
            'graphix-player': CapPagePlayer,
            'highlights': CapPageHighlight,
            'clients': CapPageClients,
			'contact': CapPageContact
        }
        
        this._animMap = {
            CapPagePrint: {
                CapPagePlayer: CapAnimFade
            },
            CapPageInternet: {
                CapPagePlayer: CapAnimFade
            },
			CapPageHighlight: {
				CapPagePlayer: CapAnimFade
			},
            CapPagePlayer: {
                CapPagePrint: CapAnimFade,
                CapPageInternet: CapAnimFade,
                CapPageHighlight: CapAnimFade,
                CapPagePlayer: CapAnim
            }
        };
        
        this._currentPage = new CapPage();
        
        this.run();
    };
    
    CapSite.prototype = {
    
        toString: function(){
            return 'CapSite';
        },
        
        initLayout: function(){
        
            var topFlash = new YAHOO.widget.SWF("top-flash-obj", IMG + "/cap/top.swf", {
                version: 9.115,
                fixedAttributes: {
                    scale: "noscale"
                }
            });
            
            this._leftSteamFlash = new YAHOO.widget.SWF("steam-left", IMG + "/cap/steam_left.swf", {
                version: 9.115,
                fixedAttributes: {
                    play: "false",
                    loop: "true",
                    wmode: 'transparent'
                }
            });
            
            this._rightSteamFlash = new YAHOO.widget.SWF("steam-right", IMG + "/cap/steam_right.swf", {
                version: 9.115,
                fixedAttributes: {
                    play: "false",
                    loop: "true",
                    wmode: 'transparent'
                }
            });
            
            
            // center site
            this._center();
            
        },
        
        initEvents: function(){
        
            // initialise history
            YAHOO.util.History.register('go', 'home', function(url){
                try {
                    this._go(url);
                } 
                catch (e) {
                    console.error(e);
                    throw e;
                }
            }, null, this);
            
            YAHOO.util.History.initialize("yui-history-field", "yui-history-iframe");
            
            // center on resize
            Event.addListener(window, 'resize', function(){
                try {
                    this._center();
                } 
                catch (e) {
                    console.error(e);
                }
            }, null, this);
            
			// no right clicky
            YAHOO.util.Event.addListener(document.body, 'contextmenu', function(e, client){
				YAHOO.util.Event.preventDefault(e);
			}, null, this); 
			
        },
        
        run: function(){
        
            // hide loading mask
            var anim = new YAHOO.util.Anim('loading-mask', {
                opacity: {
                    to: 0
                }
            });
            
            anim.onComplete.subscribe(function(){
                try {
                    Dom.get('loading-mask').parentNode.removeChild(Dom.get('loading-mask'));
                    
                    var url = YAHOO.util.History.getBookmarkedState('go') || 'intro';
                    this._go(url);
                } 
                catch (e) {
                    console.error(e);
                }
                
            }, null, this);
            
            anim.animate();
        },
        
        _center: function(){
            // center the site in the middle
            var h = Dom.getClientHeight();
            var site = Dom.get('site');
            site.style.marginTop = parseInt(h / 2 - site.offsetHeight / 2, 10) + 'px';
        },
        
        _go: function(url){
        
            console.info(this + ': go', url);
            
            // google analytics
            _gaq.push(['_trackPageview', url]);
            
            // urlState is something like: /home/tuut/kwak
            // first param is the page
            // params is the rest 
            var params = url.split('/');
            var pageName = params[0] ||
            (function(){
                throw new Error('Missing pageName in urlState')
            }());
            
            // check if requested page exists			
            var pageObj = this._pageMap[pageName] ||
            (function(){
                throw new Error('No such page: ' + pageName)
            }());
            
            // check if the requested page is the same object as the current page
            // then just load the params into that page
            if (this._currentPage instanceof pageObj) {
                this._currentPage.unload().subscribe(function(){
                    try {
                        this._currentPage.load(params);
                    } 
                    catch (e) {
                        console.error(e);
                    }
                }, null, this);
            }
            
            // else we need to close the current page and create a new one
            else {
            
                // already initialise the new page so it can do async server stuff without displaying
                var newPage = new pageObj();
                
                // unload the current (old) page so it can do animation
                this._currentPage.unload().subscribe(function(){
                    try {
                    
                        // get transition animation from the animMap and fallback to the standard 'doors' animation
                        var from = this._currentPage.toString();
                        var to = newPage.toString();
						
						//console.warn('from', from);
						//console.warn('to', to);
						
                        if (this._animMap[from] && this._animMap[from][to]) {
                            console.info('using animMap');
                            var anim = new this._animMap[from][to]();
                        }
                        else {
                            //console.info('default doors');
                            anim = new CapAnimDoors();
                        }
                        
                        // close the doors
                        anim.close().subscribe(function(){
                            try {
                                // doors are closed.. play steam
                                if (anim instanceof CapAnimDoors)
                                    this._playSteam();
                                
                                // clean up old page
                                this._currentPage.destroy();
                                
                                // load new page stuff
                                newPage.load(params).subscribe(function(){
                                    try {
                                    
                                        // when params are loaded stop the steam and open the door
                                        if (anim instanceof CapAnimDoors)
                                            this._stopSteam();

                                        anim.open().subscribe(function(){
                                            console.info(this + ': _go: anim opened');
                                            
                                            // update menu.. if the page has a pageName set use that one
                                            // else use its own name 
                                            if (newPage.menuPageName) 
                                                pageName = newPage.menuPageName;
                                            updateMenu('main-menu', pageName);
                                            
                                        }, null, this);
                                        
                                    } 
                                    catch (e) {
                                        console.error(e);
                                    }
                                    
                                }, null, this);
                                
                                this._currentPage = newPage;
                                
                            } 
                            catch (e) {
                                console.error(e);
                            }
                        }, null, this);
                    } 
                    catch (e) {
                        console.error(e);
                    }
                }, null, this);
            }
            
        },
        
        _playSteam: function(){
            Dom.get(this._leftSteamFlash._id).Play();
            Dom.get(this._rightSteamFlash._id).Play();
        },
        
        _stopSteam: function(){
            Dom.get(this._leftSteamFlash._id).Rewind();
            Dom.get(this._rightSteamFlash._id).Rewind();
        }
        
    };
    
    /**
     * CapPage
     */
    var CapPage = function(){
        console.info(this + ': constructor', arguments);
        
        this._rpc = new CAP.util.JsonBroker('/rpc/')
        this._params = [null];
    };
    
    CapPage.prototype = {
    
        _params: null,
        
        toString: function(){
            return 'CapPage';
        },
        
        load: function(params, fireNow){
        
            console.info(this + ': load', arguments);
            
            fireNow = typeof fireNow == 'undefined' ? true : false;
            this._params = params;
            
            // set the page name as a style on the content
            Dom.addClass('content', params[0]);
            
            var e = new YAHOO.util.CustomEvent();
            
            e.subscribe(function(){
            
                var anim = new YAHOO.util.Anim('content', {
                    opacity: {
                        to: 1
                    }
                }, 0.5, YAHOO.util.Easing.easeOut)
                
                anim.animate();
            }, null, this);
            
            if (fireNow) {
                setTimeout(function(){
                    e.fire();
                }, 1);
            }
            
            return e;
        },
        
        unload: function(){
            console.info(this + ': unload', arguments);
            
            var anim = new YAHOO.util.Anim('content', {
                opacity: {
                    to: 0
                }
            }, 0.5, YAHOO.util.Easing.easeOut)
            
            setTimeout(function(){
                //console.info(this + ': starting animation');
                anim.animate();
            }, 1);
            return anim.onComplete;
        },
        
        destroy: function(){
        
            // remove the page name as a style from the content div
            Dom.removeClass('content', this._params[0]);
            
            // make sure we leave it empty
            Dom.get('content').innerHTML = '';
        }
    };
    
    /**
     * CapPageIntro
     */
    var CapPageIntro = function(){
        CapPageIntro.superclass.constructor.apply(this, arguments);
    };
    YAHOO.extend(CapPageIntro, CapPage, {
    
        toString: function(){
            return 'CapPageIntro';
        },
        
        load: function(){
        
            var div = document.createElement('div');
            div.id = 'intro-flash-obj';
            
            Dom.get('content').appendChild(div);
            
            var obj = new YAHOO.widget.SWF("intro-flash-obj", IMG + "/cap/intro.swf", {
                version: 9.115,
                fixedAttributes: {
                    wmode: 'transparent'
                }
            });
            
            return CapPageIntro.superclass.load.apply(this, arguments);
        }
        
    });
    
    /**
     * CapPageProfile
     */
    var CapPageProfile = function(){
        CapPageProfile.superclass.constructor.apply(this, arguments);
    };
    YAHOO.extend(CapPageProfile, CapPage, {
        toString: function(){
            return 'CapPageProfile';
        },
        
        load: function(params){
        
            var e = CapPageIntro.superclass.load.call(this, params, false);
            
            this._rpc.call('page_content', ['profile'], function(result){
            
                try {
                    Dom.get('content').innerHTML = '';
                    var c = Dom.get('content').appendChild(document.createElement('div'));
                    c.className = 'text';
                    c.appendChild(document.createElement('h1')).innerHTML = result.title;
                    c.appendChild(document.createElement('div')).innerHTML = result.text;
                    
                    e.fire();
                    
                    new CapScroller(c, {
                        spacing: 35
                    });
                } 
                catch (e) {
                    console.error(e);
                }
            }, null, this);
            
            return e;
        }
    });
	
    /**
     * CapPageContact
     */
    var CapPageContact = function(){
        CapPageContact.superclass.constructor.apply(this, arguments);
    };
    YAHOO.extend(CapPageContact, CapPage, {
        toString: function(){
            return 'CapPageContact';
        },
        
        load: function(params){
        
            var e = CapPageIntro.superclass.load.call(this, params, false);
            
            this._rpc.call('page_content', ['contact'], function(result){
            
                try {
                    Dom.get('content').innerHTML = '';
                    var c = Dom.get('content').appendChild(document.createElement('div'));
                    c.className = 'text';
                    c.appendChild(document.createElement('h1')).innerHTML = result.title;
					
					var text = result.text;
					
					var map = '' + 
					'<div class="map">' + 
					'	<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.nl/maps?q=C.A.P.+Concepts+in+Design&amp;hl=nl&amp;sll=52.374198,4.902692&amp;sspn=0.010925,0.020664&amp;vpsrc=6&amp;hq=C.A.P.+Concepts+in+Design&amp;t=m&amp;ie=UTF8&amp;hnear=&amp;cid=10446468283135180750&amp;ll=52.38042,4.908657&amp;spn=0.018337,0.036478&amp;z=14&amp;iwloc=A&amp;output=embed"></iframe><br /><small><a href="http://maps.google.nl/maps?q=C.A.P.+Concepts+in+Design&amp;hl=nl&amp;sll=52.374198,4.902692&amp;sspn=0.010925,0.020664&amp;vpsrc=6&amp;hq=C.A.P.+Concepts+in+Design&amp;t=m&amp;ie=UTF8&amp;hnear=&amp;cid=10446468283135180750&amp;ll=52.38042,4.908657&amp;spn=0.018337,0.036478&amp;z=14&amp;iwloc=A&amp;source=embed" style="color:#0000FF;text-align:left">Grotere kaart weergeven</a></small>' +
					'</div>';
					
					text = text.replace('{{map}}', map);
					
					text = text.replace('{{logo}}', '<div style="width: 200px; height: 200px;" id="contact-logo"></div>');
					
                    c.appendChild(document.createElement('div')).innerHTML = text;
                    
                    e.fire();
					
                    var obj = new YAHOO.widget.SWF('contact-logo', IMG + "/cap/CAP_logo3d.swf", {
                        version: 9.115,
                        fixedAttributes: {
                            wmode: 'transparent'
                        }
                    });
					
                    
                    new CapScroller(c, {
                        spacing: 30
                    });
                } 
                catch (e) {
                    console.error(e);
                }
            }, null, this);
            
            return e;
        }
    });	
    
    /**
     * CapPageGraphixAbstract
     */
    var CapPageGraphixAbstract = function(){
        CapPageGraphixAbstract.superclass.constructor.apply(this, arguments);
    };
    YAHOO.extend(CapPageGraphixAbstract, CapPage, {
    
        _graphixType: null,
        _subId: null,

        toString: function(){
            return 'CapPageGraphixAbstract';
        },
        
        load: function(params){
        
            this._graphixType = params[1]; // logo, cd-artwork, retouche etc
            this._subId = params[2] || '';
            this._imageId = params[3] || '';
            
            var e = CapPageGraphixAbstract.superclass.load.call(this, params, false);
            
            Dom.get('content').innerHTML = this.getMenuHtml() +
            
            '<div id="graphix-frame">' +
            '<div id="graphix-content">' +
            '<div id="graphix-icons"></div>' +
            '<div id="graphix-icon-title"></div>' +
            '</div>' +
            '<div id="graphix-genres">' +
            '<ul id="graphix-genre-list" class="icon_category">GENRE</ul>' +
            '</div>' +
            '<div id="graphix-various-categories">' +
            '<ul id="graphix-various-categories-list" class="icon_category"></ul>' +
            '</div>' +
            '<div class="clear"></div>' +
            '</div>';
            
            this._scroller = new CapScroller(Dom.get('graphix-icons'), {
                spacing: 10
            });
            
            Dom.get('graphix-frame').className = this._graphixType;
            
            // select graphix menu
            updateMenu('graphix-menu', this._graphixType);
            
            // fill genres
            this._rpc.call('graphix_genres', [], function(genres){
            
                // hack: inject 'Show All' into front
                genres.splice(0, 0, {
                    name: 'Show All',
                    id: ''
                });
                
                for (var i in genres) {
                    var genre = genres[i];
                    var li = Dom.get('graphix-genre-list').appendChild(document.createElement('li'));
                    
                    if (genre.id == this._subId) {
                        li.innerHTML = genre.name;
                        li.className = 'active';
                    }
                    else {
                        var a = li.appendChild(document.createElement('a'));
                        a.href = '/#go=print/' + this._graphixType + '/' + genre.id;
                        a.innerHTML = genre.name;
                    }
                }
                
                
            }, null, this);
            
            // fill various categories
            this._rpc.call('various_categories', [], function(var_cats){
            
            
                var_cats.splice(0, 0, {
                    name: 'Show All',
                    id: ''
                });
            
                for (var i in var_cats) {
                    var var_cat = var_cats[i];
                    var li = Dom.get('graphix-various-categories-list').appendChild(document.createElement('li'));
                    
                    if (var_cat.id == this._subId) {
                        li.innerHTML = var_cat.name;
                        li.className = 'active';
                    }
                    else {
                        var a = li.appendChild(document.createElement('a'));
                        a.href = '/#go=print/' + this._graphixType + '/' + var_cat.id;
                        a.innerHTML = var_cat.name;
                    }
                }
                
                
            }, null, this);
            
            // load icons
            this._rpc.call('graphix', [this._graphixType, this._subId], function(logos){
            
                //console.warn('grpahi', logos);
                if (logos['text']) {
                    
                    Dom.get('graphix-icons').style.width = '598px';
                     
                    this._scroller.contentEl.innerHTML = '<div class="text" style="width: 530px;">' + logos['text'] + '</div>';
                    
                    //this._scroller.spacing = 20;
                    this._scroller.update();
                    
                    //var xy = this._scroller.contentEl
                    
                    e.fire();
                    return;
                }
                
                
                Dom.get('graphix-icons').style.width = '';
                
                
                /*
                
                // always want to see 15/30/etc icon placeholders (and 12, .. for cd-artwork)
                var fill;
                switch (this._graphixType) {
                    case 'cd-artwork':
                    case 'various':
                        fill = 12;
                        break;
                    default:
                        fill = 15;
                }
                
                var rest = logos.length % fill;
                var extra = fill - rest;
                
                */
                
                var extra = 0;
                
                for (var i = 0; i < logos.length + extra; i++) {
                    var logo = logos[i];
                    
                    var icon = document.createElement('div');
                    icon.className = 'icon';
                    this._scroller.contentEl.appendChild(icon);
                    
                    if (logo) {
                        var img = document.createElement('img');
                        img.src = logo.small_image;
                        YAHOO.util.Dom.setStyle(img, 'opacity', 0);
                        
                        Event.addListener(img, 'load', function(e, args, me){
                            args[0].appendChild(args[1]);
                            
                            new YAHOO.util.Anim(args[1], {
                                opacity: {
                                    to: 0.10
                                }
                            }, 1, YAHOO.util.Easing.easeOut).animate();
                        }, [icon, img], this);
                        
                        Event.addListener(img, 'mouseover', function(e, args, me){
                            Dom.get('graphix-icon-title').innerHTML = args[0].name;
                            
                            new YAHOO.util.Anim(args[1], {
                                opacity: {
                                    to: 1
                                }
                            }, 1, YAHOO.util.Easing.easeOut).animate();
                            
                        }, [logo, img], this);
                        
                        Event.addListener(img, 'mouseout', function(e, args, me){
                            Dom.get('graphix-icon-title').innerHTML = '';
                            
                            new YAHOO.util.Anim(args[1], {
                                opacity: {
                                    to: 0.10
                                }
                            }, 1, YAHOO.util.Easing.easeOut).animate();
                            
                        }, [logo, img], this);
                        
                        YAHOO.util.Event.addListener(icon, 'click', function(e, logo){
                            try {
                                this._clicky(logo);
                            } 
                            catch (e) {
                                console.error(e);
                            }
                        }, logo, this);
                    }
                    
                }
                
                this._scroller.update();
                
                e.fire();
                
            }, null, this);
            
            
            return e;
        },
        
        _clicky: function(logo){
            document.location.href = '#go=graphix-player/' + this._graphixType + '/' + this._subId + '/' + logo.id;
        },
        
        toString: function(){
            return 'CapPageGraphixAbstract';
        },
        
        getMenuHtml: function(){
            return '';
        }
        
        
    });
    
    /**
     * CapPagePrint
     */
    var CapPagePrint = function(){
        CapPagePrint.superclass.constructor.apply(this, arguments);
    }
    YAHOO.extend(CapPagePrint, CapPageGraphixAbstract, {
        getMenuHtml: function(){
            return '<div id="graphix-menu">' +
            '<a href="#go=print/logo"><div class="logo"></div></a>' +
            '<a href="#go=print/identity"><div class="identity"></div></a>' +
            '<a href="#go=print/cd-artwork"><div class="cd-artwork"></div></a>' +
            '<a href="#go=print/various"><div class="various"></div></a>' +
            '<a href="#go=print/retouche"><div class="retouche"></div></a>' +
            '</div>';
            
        },
        
        toString: function(){
            return 'CapPagePrint';
        }
    });
    
    /**
     * CapPageInternet
     */
    var CapPageInternet = function(){
        CapPageInternet.superclass.constructor.apply(this, arguments);
    };
    YAHOO.extend(CapPageInternet, CapPageGraphixAbstract, {
    
        zload: function(params){
        
            // call super but with 'websites' as second param so its compatible with 'graphix' page
            return CapPageInternet.superclass.load.call(this, ['websites', 'websites']);
            
        },
        
        getMenuHtml: function(){
            return '<div id="graphix-menu">' +
            '<a href="#go=internet/websites"><div class="websites"></div></a>' +
            '<a href="#go=internet/banners"><div class="banners"></div></a>' +
            '<a href="#go=internet/animation"><div class="animation"></div></a>' +
            '<a href="#go=internet/hosting"><div class="hosting"></div></a>' +
            '</div>';
            
        },
        
        _clicky: function(website){
            document.location.href = '#go=graphix-player/' + this._graphixType + '/' + this._subId + '/' + website.id;
        },
        
        toString: function(){
            return 'CapPageInternet';
        }
    });
    
    /**
     * CapPageHighlight
     */
    var CapPageHighlight = function(){
        CapPageHighlight.superclass.constructor.apply(this, arguments);
    };
    YAHOO.extend(CapPageHighlight, CapPageGraphixAbstract, {
    
        load: function(params){
        
            // call super but with 'highlights' as second param so its compatible with 'graphix' page
            return CapPageHighlight.superclass.load.call(this, ['highlights', 'highlights']);
        },
        
        _clicky: function(website){
            document.location.href = '#go=graphix-player/' + this._graphixType + '/' + this._subId + '/' + website.id;
        },
        
        toString: function(){
            return 'CapPageHighlight';
        }
    });
    
    
    
    /**
     * CapPagePlayer
     */
    var CapPagePlayer = function(){
        CapPagePlayer.superclass.constructor.apply(this, arguments);
    };
    YAHOO.extend(CapPagePlayer, CapPage, {
    
        // show graphix menu when we are in this page
        menuPageName: 'graphix',
        
        _built: false,
        _images: null,
        _img: null,
        _curr: null,
        _subpage: null,
        _subId: null,
        
        
        load: function(params){
            console.info(this + ': !! load', params);
            
            // http://127.0.0.1:8000/#go=graphix-player/<subpage-str>/<genre-id>/<image-id>
            this._subpage = params[1];
            this._subId = params[2] || '';
            var param_image_id = parseInt(params[3], 10);

            // promotion play hack
            if (this._subpage == 'promotion' && !param_image_id) {
                var _this = this;
                setTimeout(function() {
                	console.warn('promition hack play()');
                    _this._play.call(_this);
                }, 5000);
            }

			
            var e = CapPageIntro.superclass.load.call(this, params, false);
            
            // try to use the showImage method but if that errors just do the normal way            
            // dont do rpc call and interface build if done already
            try {
                this._showImageId(param_image_id);
                return;
            } 
            catch (e) {
            }
            
            // add subclass to content as well (removed in unload)
            Dom.addClass('content', this._subpage);
            
            // get images for this page/genre etc
            this._rpc.call('graphix', [this._subpage, this._subId], function(images){
            
                this._built = true;
                
                this._images = images;
                
                // flash
                Dom.get('content').innerHTML = '' +
                '<div class="b" id="screen">' +
                '	<img id="img-screen" src="/site_media/capdigital/spacer.gif">' +
                '	<div id="swf-screen"></div>' +
                '</div>' +
                '<div id="info-kader">' +
                '	<div id="info-kader-content"></div>' +
                '	<div id="info-kader-button"></div>' +
                '</div>' +
                '<div class="b" id="buttons">' +
                '	<div class="" id="player-left"></div>' +
                '	<div class="b" id="speaker"></div>' +
                '	<div class="b" id="pause"></div>' +
                '	<div class="b" id="prev"></div>' +
                '	<div class="b" id="play"></div>' +
                '	<div class="b" id="next"></div>' +
                '	<div class="b" id="info"></div>' +
                '	<div class="b" id="close"></div>' +
                '	<div class="" id="player-right"></div>' +
                '	<div class="clear"></div>' +
                '</div>';
                
                this._screen = Dom.get('screen');
                this._imgScreen = Dom.get('img-screen');
                this._swfScreen = Dom.get('swf-screen');
                
                YAHOO.util.Dom.setStyle(this._imgScreen, 'opacity', 0);
                
                YAHOO.util.Event.addListener(Dom.get('next'), 'click', this._next, null, this);
                YAHOO.util.Event.addListener(Dom.get('prev'), 'click', this._prev, null, this);
                YAHOO.util.Event.addListener(Dom.get('play'), 'click', this._play, null, this);
                YAHOO.util.Event.addListener(Dom.get('pause'), 'click', this._pause, null, this);
                YAHOO.util.Event.addListener(Dom.get('close'), 'click', this._close, null, this);
                YAHOO.util.Event.addListener(Dom.get('info'), 'click', this._toggleInfo, null, this);
                YAHOO.util.Event.addListener(Dom.get('info-kader-button'), 'click', this._toggleInfo, null, this);
                
                this._scroller = new CapScroller(Dom.get('info-kader-content'), {
                    align: 'middle'
                });
                
                var timeOut = null;
                var moveTimeOut = null;
                var animIn = null;
                var animOut = null;
                
                var doAnimIn = function(){
                    animIn && animIn.stop();
                    animOut && animOut.stop();
                    
                    var animIn = new YAHOO.util.Anim(Dom.get('buttons'), {
                        top: {
                            to: -542
                        }
                    }, 0.2, YAHOO.util.Easing.easeIn);
                    
                    animIn.animate();
                };
                
                var doAnimOut = function(){
                    animIn && animIn.stop();
                    animOut && animOut.stop();
                    
                    var animOut = new YAHOO.util.Anim(Dom.get('buttons'), {
                        top: {
                            to: -490
                        }
                    }, 0.2, YAHOO.util.Easing.easeIn);
                    animOut.animate();
                };
                
                YAHOO.util.Event.on('content', 'mouseenter', function(e){
                    clearTimeout(timeOut);
                    doAnimIn.call(this);
                }, null, this);
                
                YAHOO.util.Event.on('content', 'mouseleave', function(e){
                    timeOut = setTimeout(function(){
                        doAnimOut.call(this);
                        clearTimeout(timeOut);
                    }, 2000);
                }, null, this);
                
                YAHOO.util.Event.on('img-screen', 'mousemove', function(e){
                
                    clearTimeout(moveTimeOut);
                    
                    if (Dom.getStyle(Dom.get('buttons'), 'top') == '-490px') 
                        doAnimIn.call(this);
                    
                    moveTimeOut = setTimeout(function(){
                        doAnimOut.call(this);
                    }, 2000);
                    
                }, null, this);
                
                YAHOO.util.Event.on('img-screen', 'mouseleave', function(e){
                    clearTimeout(moveTimeOut);
                }, null, this);
                
                YAHOO.util.Event.on('info-kader', 'mouseenter', function(e){
                    YAHOO.util.Event.stopPropagation(e);
                    moveTimeOut = setTimeout(function(){
                        doAnimOut.call(this);
                    }, 100);
                }, null, this);
                
                // websites can clicky on the image
                // todo: move logic to a subclass
                if (this._subpage == 'websites') {
                    YAHOO.util.Event.on('img-screen', 'click', function(e){
                        this._openUrl();
                    }, null, this);
                }
                
                // finally show the requested image
                this._showImageId(param_image_id);
                
                e.fire();
                
            }, null, this);
            
            return e;
        },
        
        // override unload completely and fire the event directly
        // this prevents the default fade-out.. we dont wanna do it here cuz
        // we take care of our own
        unload: function(){
        	
        	console.info(this+': unload()');
        	
            var e = new YAHOO.util.CustomEvent();
			
			setTimeout(function(){
                Dom.removeClass('content', this._subpage);
                e.fire();
            }, 1);
            return e;
        },
		
		destroy: function() {
			console.info(this+': destroy() (clear playInterval)');
			clearInterval(this._playInterval);
			CapPagePlayer.superclass.destroy.call(this);
		},
        
        _showImageId: function(id){
            //console.info('_showImageId', id);
			
			// fallback to first image
			if (!id) {
				id = this._images[0].id;
			}
            
            for (var i in this._images) {
                var i = parseInt(i, 10);
                var image = this._images[i];
                if (image.id === id) {
                    this._showImage(i);
                    return;
                }
            }
            throw new Error(this + ': _showImageId: no such id: ' + id);
        },
        
        _showImage: function(i){
            //console.info(this + ': _showImage', this._images[i]);
            
            this._curr = i;
            
            var isSwf = this._images[i].big_image.substr(-3).match(/swf/i) !== null;
            
            // load image if not loaded before and return to this method
            if (!isSwf && !this._images[i].image) {
                var img = new Image();
                var _this = this;
                img.onload = function(){
                    _this._showImage(i);
                }
                img.src = this._images[i].big_image;
                this._images[i].image = img;
                
                return;
            }
            
            // load next and previous images while looking at this one
            /*
             if (i < this._images.length - 1 && !this._images[i + 1].image) {
             this._images[i + 1].image = new Image();
             this._images[i + 1].image.src = this._images[i + 1].big_image;
             }
             */
            // animate out old image if any image
            var animOut = new YAHOO.util.Anim(this._imgScreen, {
                opacity: {
                    to: 0.0
                }
            }, this._curr === null ? 0 : 0.2, YAHOO.util.Easing.easeOut);
            
            // when old image is faded out..
            animOut.onComplete.subscribe(function(){
            
                var screen = null;

				// clean up old flash                 
				this._swfScreen.innerHTML = '';
				
				// hide by default
                YAHOO.util.Dom.setStyle(this._imgScreen, 'display', 'none');
                YAHOO.util.Dom.setStyle(this._swfScreen, 'display', 'none');
				
                try {
                
                    if (!isSwf) {
                        this._imgScreen.src = this._images[i].image.src;
                        screen = this._imgScreen;
                    }
                    else {
                        
                        var obj = new YAHOO.widget.SWF(this._swfScreen.id, this._images[i].big_image, {
                            version: 9.115,
                            fixedAttributes: {
                                wmode: 'transparent'
                            }
                        });
                        
                        screen = this._swfScreen;
                        
                    }
                    
                    YAHOO.util.Dom.setStyle(screen, 'opacity', 0);
                    YAHOO.util.Dom.setStyle(screen, 'display', 'block');
                    
                    // amimate into new image
                    var animIn = new YAHOO.util.Anim(screen, {
                        opacity: {
                            to: 1.0
                        }
                    }, 0.2, YAHOO.util.Easing.easeOut);
                    
                    // update info kader
                    this._scroller.contentEl.innerHTML = '' +
                    '<strong>Name</strong>: ' +
                    this._images[i].name +
                    '<br/>' +
                    this._images[i].info +
                    this._relatedHtml(this._images[i].related);
                    
                    this._scroller.update();
                    
                    animIn.animate();
                    
                } 
                catch (e) {
                    console.error(e);
                }
                
            }, null, this);
            
            animOut.animate();
            
        },
        
        _relatedHtml: function(rel_info){
            //console.warn('rel_info', rel_info);
            var html = ''
            
            if (rel_info.length) 
                html += '<div class="related-text">RELATED</div>'
            
            for (var i in rel_info) {
                html += '<div>' +
                '<a href="' +
                rel_info[i].url +
                '">' +
                '<img src="' +
                rel_info[i].img +
                '" class="related" />' +
                '</a>' +
                '</div>';
            }
            
            return html;
            
        },
        
        _next: function(){
            if (this._curr === this._images.length - 1) 
                this._goImage(0);
            else 
                this._goImage(this._curr + 1);
        },
        
        _prev: function(){
            if (this._curr === 0) 
                this._goImage(this._images.length - 1);
            else 
                this._goImage(this._curr - 1);
        },
        
        _goImage: function(imageIndex){
            document.location.href = '#go=graphix-player/' +
            this._subpage +
            '/' +
            this._subId +
            '/' +
            this._images[imageIndex].id;
        },
        
        _play: function(){
            console.info(this + ': play');
            
            clearInterval(this._playInterval);
            
            this._playInterval = setInterval((function(_this){
                return function(){
                    _this._next();
                }
            })(this), 5000);
            
            this._next();
        },
        
        _pause: function(){
            console.info(this + ': pause');
            clearInterval(this._playInterval);
        },
        
        _close: function(){
            console.info(this + ': close', this._subpage);
            clearInterval(this._playInterval);
            
            var page = 'print';
            var subpage = this._subpage;
            
            // websites also use the player in that case go there
            // todo: move logic to subclass
            if (this._subpage == 'websites') {
                page = 'internet/websites';
                subpage = '';
            }

            if (this._subpage == 'banners') {
                page = 'internet/banners';
                subpage = '';
            }

            if (this._subpage == 'animations') {
                page = 'internet/animations';
                subpage = '';
            }
            
            if (this._subpage == 'highlights') {
                page = 'highlights';
                subpage = '';
            }
            
            document.location.href = '#go=' + page + '/' + subpage + '/' + this._subId;
        },
        
        _toggleInfo: function(){
        
            var leftShow = 586;
            var leftHide = 752;
            
            var to = Dom.getStyle(Dom.get('info-kader'), 'left') == (leftShow + 'px') ? leftHide : leftShow;
            
            var anim = new YAHOO.util.Anim(Dom.get('info-kader'), {
                left: {
                    to: to
                }
            }, 0.2, YAHOO.util.Easing.easeIn);
            anim.animate();
        },
        
        toString: function(){
            return 'CapPagePlayer';
        },
        
        _openUrl: function(){
        
        	if (this._images[this._curr].is_offline) {
        		
        		var div = document.createElement('div');
        		
        		div.innerHTML = '<div>This website is offline</div>';
        		div.className = 'website-offline';

        		YAHOO.util.Dom.setStyle(div, 'opacity', 0);
        		Dom.get('screen').appendChild(div);

	            new YAHOO.util.Anim(div, {
	                opacity: {
	                    to: 0.8
	                }
	            }, 0.5, YAHOO.util.Easing.easeOut).animate();

        		YAHOO.util.Event.addListener(div, 'click', function() {

					div.parentNode.removeChild(div);
        			
        		}, null, this);
        		
        		return;
        		
        	}
        
            var address = this._images[this._curr].address;
            if (!address) 
                throw new Exception('image has no address');
            
            window.open(address);
        }
    });
    
    var CapPageClients = function(){
        CapPageClients.superclass.constructor.apply(this, arguments);
    };
    YAHOO.extend(CapPageClients, CapPage, {
    
        load: function(params){
            var e = CapPageClients.superclass.load.call(this, params, false);
            
            Dom.get('content').innerHTML = '' +
            '<div id="clients-left">' +
            '<div id="clients-container"></div>' +
            '<div id="graphix-icon-title"></div>' +
            '</div>' +
            '<div id="clients-right"><div id="clients-info"></div></div>';
            
            this._scrollerInfo = new CapScroller(Dom.get('clients-info'), {
                align: 'middle'
            });
            
            var clientsContainer = Dom.get('clients-container');
			
            this._scroller = new CapScroller(Dom.get('clients-container'), {
				spacing: 0
            });
			
            
            this._rpc.call('clients', [], function(result){
            
                /*
                var fill = 12;
                var rest = result.length % fill;
                var extra = fill - rest;
                */
                var extra = 0;
                
                for (var i = 0; i < result.length + extra; i++) {
                    var client = result[i];
                    
                    var icon = document.createElement('div');
                    icon.className = 'icon';
                    this._scroller.contentEl.appendChild(icon);
                    
                    if (client) {
                    
                        var img = document.createElement('img');
                        img.id = 'img-client-' + client.id;
                        img.src = client.small_image;
                        
                        YAHOO.util.Dom.setStyle(img, 'opacity', 0);
						
                        Event.addListener(img, 'load', function(e, args, me){
                            args[0].appendChild(args[1]);
                            
                            new YAHOO.util.Anim(args[1], {
                                opacity: {
                                    to: 0.10
                                }
                            }, 1, YAHOO.util.Easing.easeOut).animate();
                        }, [icon, img], this);
                        
                        Event.addListener(img, 'mouseover', function(e, args, me){
                            Dom.get('graphix-icon-title').innerHTML = args[0].name;
                            
                            new YAHOO.util.Anim(args[1], {
                                opacity: {
                                    to: 1
                                }
                            }, 1, YAHOO.util.Easing.easeOut).animate();
                            
                        }, [client, img], this);
                        
                        Event.addListener(img, 'mouseout', function(e, args, me){
                            if (args[0].id == this._selected) 
                                return;
                            
                            Dom.get('graphix-icon-title').innerHTML = '';
                            
                            new YAHOO.util.Anim(args[1], {
                                opacity: {
                                    to: 0.10
                                }
                            }, 1, YAHOO.util.Easing.easeOut).animate();
                            
                        }, [client, img], this);
                        
                        YAHOO.util.Event.addListener(icon, 'click', function(e, client){
                            try {
                                this._clicky(client);
                            } 
                            catch (e) {
                                console.error(e);
                            }
                        }, client, this);
                    }
                }
                
				this._scroller.update();
                e.fire();
                
            }, null, this);
            
            return e;
        },
        
        _selected: null,
        _clicky: function(client){
        
            // unload old selected
            new YAHOO.util.Anim(Dom.get('img-client-' + this._selected), {
                opacity: {
                    to: 0.10
                }
            }, 1, YAHOO.util.Easing.easeOut).animate();
            
            this._selected = client.id;
            
            this._scrollerInfo.contentEl.innerHTML = client.info;
            this._scrollerInfo.update();
            
        }
        
    });
    
    
    
    /**
     * Main
     */
    YAHOO.namespace('CAPSITE');
    Event.on(window, 'load', function(){
        try {
            YAHOO.CAP.site = new CapSite();
        } 
        catch (e) {
            console.error(e);
        }
    });
    
})();

