function efm_module(efmId)
{
    var _this = this;
    this.carouselOptions = {
        api: true,
        size: 4,
        onSeek: function() {
            _this.validateNavigationButtons();
        }
    };
    this.efmSelector = "div.efmModule";
    this.mainWindowSelector = "div.efmModule div.mainWindow";
    //this.mainWindowNavigationSelector = this.mainWindowSelector + " div.mainNavButton";
    this.mainWindowNavigationSelectorPrev = this.mainWindowSelector + " div.mainNavButton.prev";
    this.mainWindowNavigationSelectorNext = this.mainWindowSelector + " div.mainNavButton.next";
    this.mainContentSelector = this.mainWindowSelector + " div.featureContent";
    this.mainContentBackgroundSelector = this.mainWindowSelector + " div.featureContentBackground";
    this.mainImageSelector = this.mainWindowSelector + " img.mainImage";
    this.mainImageLinkSelector = this.mainWindowSelector + " a.mainImageLink";
    this.wrapperSelector = "div.efmModule div.fCarousel div.scrollableWrapper";
    this.listSelector = this.wrapperSelector + " ul.featureList";
    this.itemSelector = this.listSelector + " li.featureItem";
    this.mainWindowNextButtonSelector = this.mainWindowNavigationSelectorNext + " a.mainNavNext";
    this.mainWindowPrevButtonSelector = this.mainWindowNavigationSelectorPrev + " a.mainNavPrev";
    this.nextButtonSelector = "div.fCarousel a.nextPage";
    this.prevButtonSelector = "div.fCarousel a.prevPage";
    this.carouselSize = jQuery(this.itemSelector).size();
    this.carouselAPI = null;
    if (efmId) {
        this.efmId = efmId;
        this.initialize();
    }

}

efm_module.prototype = 
{
    initialize: function()
    {
        this.convertMainFeatureSummaryToVideoEmbed();
        this.createScrollableCarouselApiObject();
        this.initializeCarouselItemLinks();
        this.initializeMainFeatureScrollButtons();
        this.validateNavigationButtons();
    },
    
    convertMainFeatureSummaryToVideoEmbed: function()
    {
        var $videoFeatureContainer = jQuery(this.mainWindowSelector + " div.mainVideoFeature");
        if (this.activeMainFeatureIsNotVideo()) {
             var videoJSON = $videoFeatureContainer.text();
             var embedHtml = this.getVideoEmbedHtmlFromSummaryField(videoJSON);
             $videoFeatureContainer.html(embedHtml);
        }
    },
    
    activeMainFeatureIsNotVideo: function()
    {
        var $videoFeatureContainer = jQuery(this.mainWindowSelector + " div.mainVideoFeature");
        if ($videoFeatureContainer.length > 0) {
            return true;
        } else {
            return false;
        }
    },
    
    createScrollableCarouselApiObject: function()
    {
        this.carouselAPI = jQuery(this.wrapperSelector).scrollable(this.carouselOptions);
    },
    
    initializeCarouselItemLinks: function()
    {
        var _this = this;
        jQuery(this.itemSelector).click(function(){
            var $item = jQuery(this);
            if (jQuery(this).hasClass('video')) {
                if (!_this.activeMainFeatureIsNotVideo()) {
                    _this.clearMainWindowForVideo();
                }
                _this.loadMainVideoWindow($item);
                _this.validateNavigationButtons();
            } else {
                _this.clearMainWindowForContent();
                _this.loadMainContentWindow($item);
                _this.validateNavigationButtons();
            }
        });
    },

    clearMainWindowForVideo: function()
    {
        var $contentContainer = this.getActiveFeatureContentContainer();
        if ($contentContainer.length > 0) { 
            var $mainVideoFeatureTemplate = jQuery(this.efmSelector + " div.mainVideoFeatureTemplate").clone(true);
            $mainVideoFeatureTemplate.removeClass("mainVideoFeatureTemplate");
            $mainVideoFeatureTemplate.addClass("mainVideoFeature");
            $mainVideoFeatureTemplate.hide();
            $contentContainer.after($mainVideoFeatureTemplate);
            $contentContainer.remove();
        }
    },
    getActiveFeatureContentContainer: function()
    {
        var $contentContainer = jQuery(this.mainWindowSelector + " div.mainFeature");
        if ($contentContainer.length <= 0) { 
            $contentContainer = jQuery(this.mainWindowSelector + " div.mainVideoFeature");
        }
        return $contentContainer;
    },

    loadMainVideoWindow: function($item)
    {
        var itemId = this.getFeatureId($item);
        var mainFeatureContent = this.getItemMainFeatureContent(itemId);
        var itemIsActive = jQuery(this.mainWindowSelector).hasClass("assetId_" + itemId);
        if (!itemIsActive) {
            this.registerAssetItemInMainWindowHtml($item);
            this.insertMainVideoFeatureContent(mainFeatureContent);
        }
    },
    
    /**
      * @param jQuery element $item
      * @return string
      */
     getFeatureId: function($itemElement)
     {
         var classes = $itemElement.attr('class');
         var featureIdClass = classes.match(/assetId_\d+/);
         return featureIdClass.toString().match(/\d+/).toString();
     },

     getFeaturePosition: function($itemElement)
     {
         var classes = $itemElement.attr('class');
         var featurePositionClass = classes.match(/item_\d+/);
         return featurePositionClass.toString().match(/\d+/).toString();
     },
     
     getItemMainFeatureContent: function(itemId)
     {
         var id = this.efmId+"_"+itemId;
         var mainFeature = {};
         mainFeature.style = jQuery('#style_'+id).text();
         mainFeature.imageSrc = jQuery('#image_'+id).attr('src');
         mainFeature.target = jQuery('#target_'+id).attr('href')
         mainFeature.title = jQuery('#title_'+id).text();
         mainFeature.summary = jQuery('#summary_'+id).html();
         mainFeature.byLine = jQuery('#byLine_'+id).text();
         //mainFeature.moreLink = jQuery('#moreLink_'+id+' a').attr('href');
         mainFeature.linkListHTML = jQuery('#moreLinkList_'+id).html();
         return mainFeature;
     },

     registerAssetItemInMainWindowHtml: function($itemElement)
     {
         var mainWindowClasses = jQuery(this.mainWindowSelector).attr('class');
         var registeredFeatureIdClass = mainWindowClasses.match(/assetId_\d+/);
         var featureId = this.getFeatureId($itemElement);
         jQuery(this.mainWindowSelector).removeClass(registeredFeatureIdClass);
         jQuery(this.mainWindowSelector).removeClass("full");
         jQuery(this.mainWindowSelector).removeClass("half");
         jQuery(this.mainWindowSelector).addClass(this.getItemMainFeatureContent(featureId).style);
         jQuery(this.mainWindowSelector).addClass("assetId_" + featureId);
     },
     
    insertMainVideoFeatureContent: function(mainFeatureContent)
    {
        var videoEmbedHtml = this.getVideoEmbedHtmlFromSummaryField(mainFeatureContent.summary);
        jQuery(this.mainWindowSelector + " div.mainVideoFeature").html(videoEmbedHtml);
        jQuery(this.mainWindowSelector + " div.mainVideoFeature").fadeIn('fast');
    },
    
    getVideoEmbedHtmlFromSummaryField: function(summary)
    {
        var videoJSONObject = eval('(' + summary + ')');
        var videoUrlVars = new Array();
        var embedCode = "";
        if (videoJSONObject.videoType == 'youtube') {
            videoUrlVars = this.getUrlVars(videoJSONObject.videoContent);
            embedCode = '<object width="638" height="329"><param name="movie" value="http://www.youtube.com/v/'+ videoUrlVars['v'] + '&hl=en&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/'+videoUrlVars['v']+'&hl=en&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="638" height="329"></embed></object>';
        } else if (videoJSONObject.videoType == 'blip') {
            embedCode = '<embed src="' + videoJSONObject.videoContent + '" type="application/x-shockwave-flash" width="638" height="328" allowscriptaccess="always" allowfullscreen="true"></embed>'
        } else if ( videoJSONObject.videoType == 'vimeo') {
            var vimeoVideoId = videoJSONObject.videoContent.match(/\d*$/);
            embedCode ='<object width="638" height="329"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + vimeoVideoId + '&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=' + vimeoVideoId + '&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="638" height="329"></embed></object>';
        } else if ( videoJSONObject.videoType == 'custom') {
            embedCode = unescape(videoJSONObject.videoContent);
        }
        return embedCode;
    },
    
    getUrlVars: function(url)
    {
        var vars = [], hash;
        var hashes = url.slice(url.indexOf('?') + 1).split('&');
        for (var i = 0; i < hashes.length; i++) {
            hash = hashes[i].split('=');
            vars.push(hash[0]);
            vars[hash[0]] = hash[1];   
        }
        return vars;
    },
    clearMainWindowForContent: function()
    {
        var $videoContainer = jQuery(this.mainWindowSelector + " div.mainVideoFeature");
        if ($videoContainer.length > 0) { 
            var $mainContentFeatureTemplate = jQuery(this.efmSelector + " div.mainFeatureTemplate").clone(true);
            $mainContentFeatureTemplate.removeClass("mainFeatureTemplate");
            $mainContentFeatureTemplate.addClass("mainFeature");
            $mainContentFeatureTemplate.hide();
            $videoContainer.after($mainContentFeatureTemplate);
            $videoContainer.remove();
        }
    },
    
    loadMainContentWindow: function($item)
    {
        var _this = this;
        var itemId = this.getFeatureId($item);
        var mainFeatureContent = this.getItemMainFeatureContent(itemId);
        var $mainImage = jQuery(this.mainImageSelector);
        var $mainImageLinkContainer = jQuery(this.mainImageLinkSelector);
        var itemIsActive = jQuery(this.mainWindowSelector).hasClass("assetId_" + itemId);
        if (!itemIsActive) {
            this.registerAssetItemInMainWindowHtml($item);
            jQuery(this.mainWindowSelector + " div.mainFeature").fadeIn('fast');
            $mainImageLinkContainer.fadeOut('normal');
            $mainImageLinkContainer.hide();
            $mainImage.attr('src', mainFeatureContent.imageSrc);
            jQuery(this.mainContentSelector).fadeOut('fast');
            jQuery(this.mainContentBackgroundSelector).fadeOut('fast');
            $mainImageLinkContainer.fadeIn('normal', function() {
                _this.insertMainFeatureContent(mainFeatureContent);
                jQuery(_this.mainContentSelector).fadeIn('fast');
                jQuery(_this.mainContentBackgroundSelector).fadeIn('fast');
            });
        }
    },
    
    insertMainFeatureContent: function(mainFeature)
    {
        jQuery(this.mainContentSelector +" h3 a").text(mainFeature.title);
        jQuery(this.mainContentSelector +" h3 a").attr('href', mainFeature.target);
        jQuery(this.mainContentSelector +" h4").text(mainFeature.byLine);
        jQuery(this.mainContentSelector +" span.summary").text(mainFeature.summary);
        jQuery(this.mainContentSelector +" a.moreLink").attr('href', mainFeature.target);
        jQuery(this.mainWindowSelector +" a.mainImageLink").attr('href', mainFeature.target);
        if(mainFeature.linkListHTML =='') {
            jQuery(this.mainContentSelector +" ul.moreLinkList").hide();
        } else {
            jQuery(this.mainContentSelector +" ul.moreLinkList").show();
            jQuery(this.mainContentSelector +" ul.moreLinkList").html(mainFeature.linkListHTML);
        }
        
    },
    
    initializeMainFeatureScrollButtons: function()
    {
        var _this = this;
        jQuery(this.mainWindowSelector).mouseenter(function(e){
            jQuery(_this.mainWindowNavigationSelectorNext + " a").animate({right:"0px"},100);
            jQuery(_this.mainWindowNavigationSelectorPrev + " a").animate({left:"0px"},100);
        }).mouseleave(function(e) {
            jQuery(_this.mainWindowNavigationSelectorNext + " a").animate({right:"-63px"},100);
            jQuery(_this.mainWindowNavigationSelectorPrev + " a").animate({left:"-63px"},100);
        });
        
        jQuery(this.mainWindowNextButtonSelector).click(function(){
            jQuery(_this.itemSelector + ".active").next().trigger('click');
            _this.validateNavigationButtons();
            return false;
        });
        jQuery(this.mainWindowPrevButtonSelector).click(function(){
            jQuery(_this.itemSelector + ".active").prev().trigger('click');
            _this.validateNavigationButtons();
            return false;
        });
    },
    
    validateNavigationButtons: function() 
    {
        this.enableNavButtons();
        if (this.selectedFeatureIsLast()) {
            jQuery(this.mainWindowNextButtonSelector).hide(); 
        } 
        /* should i be testing for page position or visual position? */
        if (this.selectedScrollPageIsLast()) {
            jQuery(this.nextButtonSelector).hide();
        }
        
        if (this.selectedFeatureIsFirst()) {
            jQuery(this.mainWindowPrevButtonSelector).hide();
        } 
        
        if (this.selectedScrollPageIsFirst()) {
            jQuery(this.prevButtonSelector).hide();  
        }
    },
    
    enableNavButtons: function() 
    {
        jQuery(this.mainWindowNextButtonSelector).show();
        jQuery(this.mainWindowPrevButtonSelector).show();
        jQuery(this.nextButtonSelector).show();
        jQuery(this.prevButtonSelector).show();
    },
    
    selectedFeatureIsLast: function() 
    {    
        var selectedFeaturePosition = this.getSelectedFeaturePosition();
        var lastFeaturePosition = jQuery(this.itemSelector).length;
        if ( selectedFeaturePosition == lastFeaturePosition) {
            return true;
        } else {
            return false;
        }
    },
    
    selectedFeatureIsFirst: function() 
    {
        var selectedFeaturePosition = this.getSelectedFeaturePosition();
        if (selectedFeaturePosition == "1") {
            return true;
        } else {
            return false;
        }
    },
    
    getSelectedFeaturePosition: function() 
    {
        var $selectedFeature = jQuery(this.itemSelector + ".active");
        return this.getFeaturePosition($selectedFeature);
    },
    
    selectedScrollPageIsFirst: function() 
    {
        if (this.carouselAPI.getPageIndex() == 0) {
            return true;
        } else {
            return false;
        }
    },
    selectedScrollPageIsLast: function() 
    {
        if (this.carouselAPI.getPageIndex() == (this.carouselAPI.getPageAmount() - 1)) {
            return true;
        } else {
            return false;
        }
    }, 

    /* The following functions are used as an api from EE CP */
    updateAssetFromAssetItem: function(assetItem)
    {
        if (this.assetItemIsRegisteredOnMainWindow(assetItem)) {
            this.updateEfmMainWindowFromAssetItem(assetItem);
        }
        this.updateEfmAssetFromAssetItem(assetItem);
        this.updateEfmThumbFromAssetItem(assetItem);
    },
    
    assetItemIsRegisteredOnMainWindow: function(assetItem)
    {
        return jQuery(this.mainWindowSelector).hasClass("assetId_" + assetItem.assetId);
    },
    
    updateEfmMainWindowFromAssetItem: function(assetItem)
    {
        
        jQuery(this.mainContentSelector + " span.summary").text(assetItem.assetSummary);
        jQuery(this.mainContentSelector + " h3 a").text(assetItem.assetTitle);
        jQuery(this.mainContentSelector + " h3 a").attr('href', assetItem.assetTarget);
        jQuery(this.mainContentSelector + " h4").text(assetItem.assetByLine);
        jQuery(this.mainImageSelector).attr('src',assetItem.assetMainImageSrc);
        //jQuery(this.mainContentSelector + " ul.moreLinkList").html(mainFeatureContent.linkListHTML);
    },
    
    updateEfmAssetFromAssetItem: function(assetItem)
    {
        var id = assetItem.efmId + "_" + assetItem.assetId;
        jQuery('#style_' + id).text(assetItem.assetStyle);
        jQuery('#image_' + id).attr('src', assetItem.assetMainImageSrc);
        jQuery('#target_' + id).attr('href', assetItem.assetTarget);
        jQuery('#title_' + id).text(assetItem.assetTitle);
        jQuery('#summary_' + id).text(assetItem.assetSummary);
        jQuery('#byLine_' + id).text(assetItem.assetByLine);
        // jQuery('#moreLinkList_'+id).html();
    },
    
    updateEfmThumbFromAssetItem: function(assetItem)
    {
        $item = jQuery(this.itemSelector + ".assetId_" + assetItem.assetId)
        $item.find("img").attr('src', assetItem.assetThumbImageSrc);
        $item.find("h4").text(assetItem.assetThumbTitle);
        $item.find("p").text(assetItem.assetThumbSubtitle);
    }
}
