var FlashGallery = new JS.Class({
    include: JS.Observable,
    
    on: function(eventName, callback, scope) {
        this.addObserver(function() {
            var args = Array.from(arguments), message = args.shift();
            if (message != eventName) return;
            callback.apply(scope || null, [this].concat(args));
        }, this);
    },
    
    initialize: function(element, flashSource, config, options) {
        this._element = element;
        this._flashSource = flashSource;
        this._config = config || {};
        this._options = options || {};
    },
    
    setup: function() {
        var flashVersion = deconcept.SWFObjectUtil.getPlayerVersion();
        if (flashVersion.major < 8) return this.handleNoFlash();
        
        this._elements = {};
        this._entries = this.klass.Entry.fromConfig(this, this._config);
        this._element.parentNode.insertBefore(this.getHTML(), this._element.nextSibling);
        
        var video = this.findEntryByURL(null);
        if (video) this.displayEntry(video);
        
        this.setupSlider();
    },
    
    handleNoFlash: function() {
        this._element.innerHTML = '<div class="noflash">You need Adobe Flash player installed ' +
            'to view this content. You can <a href="http://www.adobe.com/products/flashplayer/">' +
            'download Flash</a> from the Adobe website.</div>';
    },
    
    getHTML: function() {
        var elements = this._elements;
        if (elements._container) return elements._container;
        var container = elements._container = document.createElement('div');
        container.className = this.klass.CONTAINER_CLASS;
        var slider = elements._slider = document.createElement('div');
        slider.className = this.klass.SLIDER_CLASS;
        container.appendChild(slider);
        return container;
    },
    
    getContainer: function() {
        return this.getHTML();
    },
    
    getSlider: function() {
        this.getHTML();
        return this._elements._slider;
    },
    
    setupSlider: function() {
    	var pager = new Ojay.Paginator(this._elements._slider, {
    		rows:		5,
    		columns:	1,
    		direction:	'vertical'
    	}).setup();
    	
    	pager.addControls('after');
    },
    
    findEntryByURL: function(url) {
        for (var i = 0, n = this._entries.length; i < n; i++) {
            if (this._entries[i].getVideoSource() == url)
                return this._entries[i];
        }
        return this._entries[0] || null;
    },
    
    displayEntry: function(entry) {
        if (!entry.getType) return;
        var oldEntry = this.getCurrentEntry();
        this._currentEntry = entry;
        
        switch (entry.getType()) {
            case 'media':
                this.swapSWF(this.swfDataFromEntry(entry));
                break;
        }
        
        this.notifyObservers('itemchange', oldEntry, this.getCurrentEntry());
    },
    
    swapSWF: function(data) {
        var so, region = YAHOO.util.Dom.getRegion(this._element);
        var width = region.right - region.left, height = region.bottom - region.top;
        
        so = new SWFObject(this._flashSource, 'small-videoplayer', width, height, 9, this.getBackgroundColor());
        so.addParam("allowfullscreen", "true");
        so.addParam("allowScriptAccess", "always");
        so.addParam("wmode", "transparent");
        so.addVariable("trackingJS", this.klass.TRACKING_FUNCTION);
        for (var param in data) so.addVariable(param, data[param]);
        so.write(this._element);
    },
    
    swfDataFromEntry: function(entry) {
        return {};
    },
    
    getBackgroundColor: function() {
        return '#ffffff';
    },
    
    getCurrentEntry: function() {
        return this._currentEntry;
    },
    
    extend: {
        CONTAINER_CLASS:    'flash-thumbs',
        SLIDER_CLASS:       'slider',
        PREV_BUTTON_CLASS:  'button previous',
        NEXT_BUTTON_CLASS:  'button next',
        PAGING_CLASS:       'flash-thumbs-paging',
        TRACKING_FUNCTION:  'trackVideoView',
        
        Entry: new JS.Class({
            extend: {
                ITEM_CLASS: 'item',
                
                fromConfig: function(gallery, config) {
                    var entries = [], block;
                    for (var thumbpath in config) {
                        if (!config.hasOwnProperty(thumbpath)) continue;
                        block = config[thumbpath];
                        block.thumbPath = thumbpath;
                        entries.push(new this(gallery, block));
                    }
                    return entries;
                }
            },
            
            initialize: function(gallery, config) {
                this.gallery = gallery;
                this._config = config;
                this._elements = {};
                this.gallery.getSlider().appendChild(this.getHTML());
                
                var self = this;
                
                YAHOO.util.Event.on(this.getContainer(), 'click', function() {
                    gallery.displayEntry(self);
                });
                
                if (!this.getCaption()) return;
                this._tooltip = new FlashGallery.Tooltip();
                this._tooltip.setText(this.getCaption());
                YAHOO.util.Event.on(this.getContainer(), 'mouseover', this._tooltip.method('show'));
                YAHOO.util.Event.on(this.getContainer(), 'mouseout', this._tooltip.method('hide'));
            },
            
            getHTML: function() {
                var elements = this._elements;
                if (elements._container) return elements._container;
                
                var container = elements._container = document.createElement('div');
                container.className = this.klass.ITEM_CLASS;
                
                var image = elements._image = document.createElement('img');
                image.src = this.getThumbnailSource();
                var dims = this.getThumbnailSize();
                image.width = dims.width;
                image.height = dims.height;
                
                container.appendChild(image);
                
                var playicon = elements._playicon = document.createElement('span');
                playicon.className = 'playicon';
                
                container.appendChild(playicon);
                
                return container;
            },
            
            getContainer: function() {
                return this.getHTML();
            },
            
            getRegion: function() {
                return YAHOO.util.Dom.getRegion(this.getContainer());
            },
            
            getImage: function() {
                this.getHTML();
                return this._elements._image;
            },
            
            getThumbnailSource: function() {
                return this._config.thumbPath || null;
            },
            
            getThumbnailSize: function() {
                return {
                    width: this._config.thumbWidth,
                    height: this._config.thumbHeight
                };
            },
            
            getType: function() {
                return this._config.type || null;
            },
            
            getCaption: function() {
                return this._config.caption || null;
            }
        }),
        
        Tooltip: new JS.Class({
            initialize: function() {
                this._element = document.createElement('div');
                this._element.className = 'tooltip';
                this._element.style.zIndex = 40000;
                document.body.appendChild(this._element);
                
                this.hide();
                YAHOO.util.Event.on(document.body, 'mousemove', this.method('updatePosition'));
            },
            
            updatePosition: function(evnt) {
                if (!this._visible) return;
                var position = YAHOO.util.Event.getXY(evnt);
                FlashGallery.setStyle(this._element, {
                    position:   'absolute',
                    left:       (position[0] - 18) + 'px',
                    top:        (position[1] + 16) + 'px'
                });
            },
            
            setText: function(text) {
                this._element.innerHTML = text;
            },
            
            show: function() {
                this._visible = true;
                this._element.style.display = '';
            },
            
            hide: function() {
                this._visible = false;
                this._element.style.display = 'none';
            }
        }),
        
        setStyle: function(element, styles) {
            for (var style in styles)
                YAHOO.util.Dom.setStyle(element, style, styles[style]);
        }
    }
});

var WebcastGallery = new JS.Class(FlashGallery, {
    initialize: function() {
        this.callSuper();
        this.klass._instance = this;
    },
    
    swfDataFromEntry: function(entry) {
        return {
            videoPath:      entry.getVideoSource() || '',
            picPath:        entry.getHoldingImageSource() || '',
            captionText:    entry.getCaption() || '',
            shareBtn:       'WebcastGallery.share',
            rssBtn:         'WebcastGallery.showRSS'
        };
    },
    
    getBackgroundColor: function() {
        return '#000000';
    },
    
    extend: {
        CAPTION_CLASS:  'flash-gallery-caption',
        OVERLAY_CLASS:  'share-overlay',
        OVERLAY_ID:     'overlayContent',
        SHARE_URL:      '/share.html?url=',
        
        getInstance: function() {
            return this._instance || null;
        },
        
        share: function() {
            var instance = this.getInstance();
            if (!instance) return;
            var url = instance.getCurrentEntry().getPermalink();
            if (!url) return alert('Sorry, this video cannot be shared at the moment');
            _$('#' + this.OVERLAY_ID).setStyle('top', (YAHOO.util.Dom.getDocumentScrollTop(document) + 50) + 'px');
            url = encodeURIComponent(decodeURIComponent( url ));
            showOverlay(this.SHARE_URL + url, this.OVERLAY_CLASS, 0.95, 'Cancel', this.hijackShareForm.bind(this));
        },
        
        hijackShareForm: function() {
            var form = _$('.share-form form').el[0], Y = YAHOO.util;
            if (!form) return;
            
            Y.Event.on(form, 'submit', function(e) {
                Y.Event.preventDefault(e);
                Y.Connect.setForm(form);
                Y.Connect.asyncRequest('POST', form.action, {
                    success: function(response) {
                        var overlay = _$('#' + this.OVERLAY_ID);
                        overlay.setContent(response.responseText);
                        
                        // showOverlay should be refactored to clean this up
                        overlay.create('div', {id: 'overlayCloseButton'}, function(el) {
                            this.append(el);
                            _$(el).setContent('Close').on('click', function(el) {
                                hideOverlay(this.OVERLAY_CLASS, 0.95);
                            });
                        });
                        
                        this.hijackShareForm();
                        
                    }.bind(this)
                });
                Y.Connect.resetFormState();
            }.bind(this));
            
            // Hijack privacy link
            var privs = _$('a[href=/privacy.html]').el;
            var link = privs.pop();
            if (!link) return;
            
            var container = _$('#privacyStatement'), height, visible = false;
            
            Y.Event.on(link, 'click', function(e) {
                Y.Event.preventDefault(e);
                visible
                        ? container.animate({opacity: {to: 0}, height: {to: 0}}, 0.5, Y.Easing.easeOut, {
                            after: function() { visible = false; }
                        })
                        
                        : container.animate({opacity: {to: 1}, height: {to: height}}, 0.5, Y.Easing.easeOut, {
                            after: function() { visible = true; }
                        });
            });
            Y.Connect.asyncRequest('GET', '/privacy-no-layout.html', {
                success: function(response) {
                    container.setContent(response.responseText);
                    var region = Y.Dom.getRegion(container.el[0]);
                    height = region.bottom - region.top;
                    container.setStyle('height', 0).setStyle('opacity', 0);
                }
            });
        },
        
        showRSS: function() {
            var instance = this.getInstance();
            if (!instance) return;
            window.location.href = instance.getCurrentEntry().getRSSLink();
        },
        
        Entry: new JS.Class(FlashGallery.Entry, {
            
            getVideoSource: function() {
                return this._config.src || null;
            },
            getHoldingImageSource: function() {
                return this._config.holdingImage || null;
            },
            getPermalink: function() {
                return this._config.permalink || null;
            },
            getRSSLink: function() {
                return this._config.playlist || null;
            }
        })
    }
});

var SlideshowGallery = new JS.Class(FlashGallery, {
    swfDataFromEntry: function(entry) {
        return {
            xmlPath:        entry.getXMLPath() || '',
            galleryID:      entry.getGalleryID() || '',
            category:       entry.getCategory() || ''
        };
    },
    
    getBackgroundColor: function() {
        return '#ffffff';
    },
    
    extend: {
        Entry: new JS.Class(FlashGallery.Entry, {
            getTitle: function() {
                return this._config.title || null;
            },
            getXMLPath: function() {
                return this._config.xmlPath || null;
            },
            getGalleryID: function() {
                return this._config.galleryId || null;
            },
            getCategory: function() {
                return this._config.category || null;
            },
            getVideoSource: function() {
                return this.getGalleryID();
            }
        })
    }
});
