/**
 * gallery.js
 * PB 13/03/08
 * Provides an in window pop-up which hosts an image, 
 * image title and close button. While the images loads 
 * the user is presented with an animated preloader (gif).
 * Also provides an overlay behind the image which dims
 * additional page content;
 *
 * Dependancies:
 * ===================================
 * base.js  http://dean.edwards.name/weblog/2006/03/base/
 * event.js http://dean.edwards.name/weblog/2005/10/add-event2/
 * preloader.js 
 */

var Gallery = Base.extend({

    img: null,
    preloader: null, 
    gallery: null,
    overlay: null,
    wrapper: null,
    title: null,
    
    /**
     * @param   id{String}  id of the ul containing gallery links;
     * @param   img{String} animated gif to use in preloader;
     */
    constructor: function( id, img ) {
        if( ! document.getElementById ||
            ! document.getElementsByTagName ){
            return false;
        }
	},
	
	init: function( id, img ){
	    var div = document.getElementById( id );
        var links = div.getElementsByTagName("a");
       
        for(var i = 0; i < links.length; i++ ){
            if (links[i].rel.toLowerCase().indexOf("mediaplayer")!=-1) {
				addEvent( links[i], "click", this.fire(this, this.loadImage) );
			}
       };  
      
      this.build( id, img );
	},
	
	/**
     * **TO DO** needs a tidy up;
     */
	build: function( id, img ){
		var body = document.getElementsByTagName("body")[0];
		this.setIframe();
		// overlay;	
		this.overlay = document.createElement("div");
		this.overlay.id = "ui-overlay";
		this.overlay.style.width = this.galleryWidth() + "px";
		this.overlay.style.height = this.galleryHeight() + "px";
		// now in Flash
		//addEvent( this.overlay, "click", this.fire(this, this.remove) );
		body.appendChild(this.overlay);
		
		// gallery;
		this.gallery = document.createElement("div");
		this.gallery.id = "gallery";
		
		// wrap;
		this.wrapper = document.createElement("div");
		this.wrapper.id = "gallery-image";
		this.gallery.appendChild(this.wrapper);
		
		// title;
		this.title = document.createElement("p");
		this.gallery.appendChild( this.title );
		this.title.style.display = "none";
		
		// close link;
		/*
		    var link = document.createElement("a");
		        link.href = "#";
		    var text = document.createTextNode("Close");
		        link.appendChild( text );
    		
    		    	
		    this.gallery.appendChild( link );
		    addEvent( link, "click", this.fire(this, this.remove) );
		*/
		// preloader;
		this.preloader = new Preloader( img, 50, 50 ); 
      	var div = this.preloader.getHTML();
      	    div.style.margin = "10px 0 0 10px";
		this.wrapper.appendChild( div );
		
		body.appendChild(this.gallery);
		this.gallery.style.display = "none";

	},

	galleryHeight: function(){
		var de = document.documentElement;
		return self.innerHeight ||
			( de && de.clientHeight ) ||
				document.body.clientHeight;
	},
	
	galleryWidth: function(){
		var de = document.documentElement;
		return self.innerWidth ||
			( de && de.clientWidth ) ||
				document.body.clientWidth;
	},

	showGallery: function(){
		this.preloader.show();
		this.setOpacity( this.overlay, 75 );
		this.show( this.overlay );
		this.show( this.gallery );
	},
	
	show: function( elem ){
	    return elem.style.display = "block";
	},
	
	hideGallery: function(){
	    this.hide( this.gallery );
	    this.hide( this.overlay );
	},
	
	hide: function( elem ){
	    return elem.style.display = "none";
	},
	
	/**
	 * All gallery events are handled by fire(), no error 
	 * handling, probably should impliment this;
     * @param   callee{Object}  context to run the callback in;
     * @param   func{Object}    callback to run when event fires;
     * "return closure providing ref to current object;
     */
	fire: function( callee, func ){
	   return function( e ){    
	   		func.call( callee, e );
	   		return stopDefault(e);
	   };
	},
	
	
	loaded: function( img ){
		this.img = img;
		// provide reference to current object to by-pass 
		// setTimeout()'s resetting of context to window;
	    var gallery = this;
        setTimeout(function(){
                gallery.showImage();
            }, 500 );
	},
	
	loadImage: function( e ){
	    var evt, tar, img, txt;
	    evt = e || window.event;
	    tar = evt.target || evt.srcElement;
        
		if( this.img ){
			this.remove( this.img );
		};
		
		if( this.title.firstChild ){
		    this.remove( this.title.firstChild );
		};

		img = tar.parentNode.href;
		txt = document.createTextNode(tar.alt);
		this.title.style.visibility = "hidden";
		this.title.appendChild( txt );
		this.preloader.load( img, this.loaded, this );
		this.showGallery();
	},
	
	remove: function( elem ){
         return  elem.parentNode.removeChild( elem );
	},
	
	showImage: function(){
		this.preloader.hide();
		this.hide( this.img );
		this.wrapper.appendChild( this.img );
		// IE filters aren't target-able 
		// until img node is in the DOM;
		this.setOpacity( this.img, 0 );
		this.show( this.img );
		this.fadeIn( this.img );
		this.title.style.visibility = "visible";
		this.adjust();
	},

	fadeIn: function( el ){
       for( var i = 0; i <= 100; i += 5 ){
          var gallery = this;
          (function(){
                var pos = i;
                setTimeout(function(){
                    gallery.setOpacity( el , pos );
                }, ( pos + 1 ) * 10 );
          })();
        };
    },
    
    setOpacity: function( elem, level ){
        // check for IE's filters if not use w3c;
        if( elem.filters ){
            elem.style.filter = 'alpha( opacity = ' + level + ')';
        }else{
            elem.style.opacity = level / 100;
        };
    },
    
    adjust: function(){
        var w = this.getWidth(this.gallery);
        var h = this.getHeight(this.gallery);
        var l = this.scrollX() + ( this.windowWidth() / 2 ) - ( w / 2);
        var t = this.scrollY() + ( this.windowHeight() / 2 ) - ( h / 2);
        if( l < 0 ){
            l = 0;
        };
        if( t < 0 ){
            t = 0;
        }
        this.setOverlay();
        this.setX( this.gallery, l );
        this.setY( this.gallery, t );
        window.onresize = document.onscroll = this.reset( this, this.adjust );
    },
    
    setOverlay: function(){
	    /*this.overlay.style.width = this.windowWidth() + "px";
		this.overlay.style.height = this.windowHeight() + this.scrollY() + "px";*/
		this.overlay.style.width = this.scrollX()+this.windowWidth() + "px";
		//console.log(document.body.scrollHeight + "="+(this.scrollY()+this.windowHeight()));
		this.overlay.style.height = this.scrollY()+this.windowHeight() + "px";
		//alert(this.windowHeight());
	},
    
    reset: function( callee, func ){
	   return function( e ){
	   		func.call( callee, e );
	   };
	},
    
    // property marginLeft rather than left
    // used to fix scrolling window issue;
    setX: function( obj, val ){
         obj.style.marginLeft = val + "px";
    },
    
    setY: function( obj, val ){
         obj.style.marginTop = val + "px";
    },
    
    scrollX: function(){
	    var de = document.documentElement;
	    return self.pageXOffset ||
	        ( de && de.scrollLeft ) ||
	            document.body.scrollLeft;
	},
	
	scrollY: function(){
	    var de = document.documentElement;
	    return self.pageYOffset ||
	        ( de && de.scrollTop ) ||
	            document.body.scrollTop;
	},
	
	windowWidth: function(){
		var de = document.documentElement;
		return self.innerWidth || 
			( de && de.clientWidth ) ||
				document.body.clientWidth;
	},
	
	windowHeight: function(){
		var de = document.documentElement;
		return self.innerHeight || 
			( de && de.clientHeight ) ||
				document.body.clientHeight;
	},
	
    getHeight: function( elem ){
		return parseInt( this.getCSS( elem, 'height' ) );
	},
	
	getWidth: function( elem ){
		return parseInt( this.getCSS( elem, 'width' ) );
	},
	
	getCSS: function( elem, name ){
	    //if style set as a DOM property;
	    if( elem.style[name] ){
	        return elem.style[name];
	    }
	    //else if IE...;
	    else if( elem.currentStyle ){
	        /**TO DO** needs sorting!!!!!*/
	        if( name == "width" && 
	            elem.currentStyle[name] == "auto" ){
	            return elem.offsetWidth;
	        }else if (  name == "height" && 
	                    elem.currentStyle[name] == "auto" ){
	            return elem.offsetHeight;
	        }else{
	            return elem.currentStyle[name];
	        }
	    }//...else if w3c, if it exists;
	    else if(    document.defaultView && 
	                document.defaultView.getComputedStyle ){
	      name = name.replace(/([A-Z])/g, "-$1");
	      name = name.toLowerCase();
	      var s = document.defaultView.getComputedStyle( elem, "" );
	      return s && s.getPropertyValue(name);
	    }else{
	       return null; 
	    }
	}
});
