var Media = {
    _LIVE: true,
    _VOD: false,
    _MINMODE: 0,
    _MAXMODE: 1,
    /* Whenever a new method is added, add the name of the method and the type value to this array. */
    TYPE: {
    		_AbstractMedia: "Abstract Media",
    		LPMedia: "League Pass",
    		ALPMedia:"Audio League Pass",
    		XMPMedia: "XMP",
    		EVPMedia: "EVP",
			LEXMPMedia: 'LEXMP'
    }
}
Media._AbstractMedia = Class.create({
    initialize: function(data){
        this._data = Object.extend({
            id: "",
            title: "",
            bitrate: 0,
            delivery: false
        }, data ||
        {});
		this._type = Media.TYPE._AbstractMedia;
		this._isVideo = false;
    },
    getId: function(){
        return this._data.id;
    },
    getTitle: function(){
        return this._data.title;
    },
    getDelivery: function(){
        return this._data.delivery ? "Live" : "VOD";
    },
    getType: function(){
        return this._type;
    },
    toString: function(){
        return "id: " + this.getId() + "; " +
        "title: " +
        this.getTitle() +
        "; " +
        "stream: " +
        this.getDelivery() +
        "; ";
    },
    isVideo: function(){
        return this._isVideo;
    }
});
Media.LPMedia = Class.create(Media._AbstractMedia, {
    initialize: function($super, data){
        $super(Object.extend({
            homeTeam: "",
            visitingTeam: "",
            mode: Media._MAXMODE,
            cdn: ""
        }, data ||
        {}));
        this._type = Media.TYPE.LPMedia;
		this._isVideo = false;
    },
    getHomeTeam: function(){
        return this._data.homeTeam;
    },
    getVisitingTeam: function(){
        return this._data.visitingTeam;
    },
    getMatchup: function(){
        return this.getVisitingTeam() + " @ " + this.getHomeTeam();
    },
    getCDN: function(){
        return this._data.cdn + (this._data.bitrate > 0 ? (" " + this._data.bitrate + "k") : "");
    },
    getMode: function(){
        switch (this._data.mode) {
            case Media._MINMODE:
                return "Mini Mode";
            case Media._MAXMODE:
                return "Max Mode";
            default:
                return "Unknown mode";
        }
    },
    toString: function($super){
        return $super() +
        "matchup: " +
        this.getMatchup() +
        "; " +
        "mode: " +
        this.getMode() +
        "; " +
        "cdn: " +
        this.getCDN() +
        ";";
    }
});
Media.ALPMedia = Class.create(Media._AbstractMedia, {
    initialize: function($super, data){
        $super(Object.extend({
            homeTeam: "",
            visitingTeam: ""
        }, data ||
        {}));
        this._type = Media.TYPE.ALPMedia;
		this._isVideo = false;
    },
    getHomeTeam: function(){
        return this._data.homeTeam;
    },
    getVisitingTeam: function(){
        return this._data.visitingTeam;
    },
    getMatchup: function(){
        return this.getVisitingTeam() + " @ " + this.getHomeTeam();
    },
    toString: function($super){
        return $super() +
        "matchup: " +
        this.getMatchup() +
        "; ";
    }
});
Media.XMPMedia = Class.create(Media._AbstractMedia, {
    initialize: function($super, data){
        $super(Object.extend({
            category: "",
            playerType: ""
        }, data ||
        {}));
        this._type = Media.TYPE.XMPMedia;
		this._isVideo = true;
    },
    getCategory: function(){
        return this._data.category;
    },
    getPlayerType: function(){
        return this._data.playerType;
    },
    toString: function($super){
        return $super() +
        "category: " +
        this.getCategory() +
        "; " +
        "playerType: " +
        this.getPlayerType() +
        "; ";
    }
});
Media.EVPMedia = Class.create(Media.XMPMedia, {
    initialize: function($super, data){
        $super(Object.extend({
            host: "", //window.top.location.href,
            playerType: "embedded"
        }, data ||
        {}));
        this._type = Media.TYPE.EVPMedia;
		this._isVideo = true;
    },
    getHost: function(){
        return this._data.host;
    },
    toString: function($super){
        return $super() +
        "host: " +
        this.getHost() +
        "; ";
    }
});

Media.LEXMPMedia = Class.create(Media.XMPMedia, {
    initialize: function($super, data){
        $super(Object.extend({
            host: "", //window.top.location.href, // for exteral domains
            playerType: "embedded"
        }, data ||
        {}));
        this._type = Media.TYPE.LEXMPMedia;
		this._isVideo = true;
    },
    getHost: function(){
        return this._data.host;
    },
    toString: function($super){
        return $super() +
        "host: " +
        this.getHost() +
        "; ";
    }
});

var EventHandler = {
    _log: LogFactory.getLog("EventHandler"),
    _q: new Array(),
    
    /**** MICRO-TRACKING BASED CALLBACKS ****/
    
    // Handles the start of a video stream
    onStreamStart: function(media){
        this._log.info("A stream start event was received for media: [" + media.toString() + "]");
        if (!this._isValidMedia(media)) {
            this._log.error("Media object was invalid. Unfortunately, Omniture cannot continue. Invalid media: " + media.toString());
            return false;
        }
        var s = s_gi(s_account);
        s.linkTrackVars = "prop1,prop2,prop3,prop4,prop5,prop6,prop7,prop8,prop9,prop10,prop19,eVar1,eVar2,eVar3,eVar4,eVar5,eVar6,eVar7,eVar9,eVar10,eVar11,eVar15,events";
        s.linkTrackEvents = "event3,event4,event6,event11,event12";
        this._prepVars(s);
        s.prop4 = media.getId();
        s.prop5 = media.getTitle();
        s.prop6 = media.getType();
        this._queue("event6");
        if (media.getType() == Media.TYPE.LPMedia) {
            s.prop7 = media.getTitle();
            s.eVar4 = media.getId();
            s.eVar5 = media.getTitle();
            s.eVar7 = media.getMode();
            s.eVar9 = media.getHomeTeam();
            s.eVar10 = media.getVisitingTeam();
            s.eVar11 = media.getMatchup();
            s.eVar15 = media.getCDN();
            if (media.getDelivery() == "Live") {
                this._queue("event3");
			} else {
                this._queue("event4");
			} 
        } else if (media.getType() == Media.TYPE.ALPMedia) {
			s.prop9 = media.getTitle();
			s.eVar4 = media.getId();
			s.eVar6 = media.getTitle();
			s.eVar9 = media.getHomeTeam();
			s.eVar10 = media.getVisitingTeam();
			s.eVar11 = media.getMatchup();
			if (media.getDelivery() == "Live")  {
				this._queue("event11");
			} else {
				this._queue("event12");
			}
		} else if (media.isVideo()) {
			s.prop8 = media.getTitle();
			s.prop10 = media.getPlayerType();
			if ((media.getType() == Media.TYPE.LEXMPMedia) && (media.getHost())) {
				s.prop19 = media.getHost();
			}
		}
        
        s.tl(true, 'o', "EventHandler.onStreamStart");
        
        // Nielsen (on start)
        if (window.location.hostname.match(/nba\.com$/)) {
            var imgSrc = 'http://secure-us.imrworldwide.com/cgi-bin/m?ci=us-100429&tl=dav0-' +
            encodeURIComponent(media.getTitle()) +
            '&c6=vc,c08&cc=1&rnd=' +
            Math.ceil(Math.random() * 1000000000);
            this._log.debug("Sending Nielsen tracking call for stream start: " + imgSrc);
            img = new Image();
            img.src = imgSrc;
        }
        else {
            this._log.info("Ignoring Nielsen tracking call for view from: " + window.location.hostname);
        }

		// other tracking pings for video content
		if (media.isVideo()) {
			// searchignite.com start
			var siimage = new Image(); 
			siimage.src = 'http://track.searchignite.com/si/CM/Tracking/TransactionTracking.aspx?siclientid=3114&transactionamount=0&SICustTransType=12679&jscript=0&rnd=' + Math.ceil(Math.random() * 1000000000);
			this._log.info('Sending searchignite.com tracking call for video start: \n' + siimage.src);

			//doubleclick start			
			var doubleclick_image = new Image();
			var axel = Math.random();
			var a = axel * 10000000000000;
			doubleclick_image.src = 'http://ad.doubleclick.net/activity;src=1990986;type=nbaco993;cat=nbavi811;ord='+ a + '?';
			this._log.info('Sending ad.doubleclick.net tracking call for video start: \n' + doubleclick_image.src);
		}

        this._clearQueue();
        return true;
    },
    
    // Handles the end of a video stream
    // Triggers a micro call
    onStreamEnd: function(media){
        this._log.info("A stream end event was received for media: [" + media.toString() + "]");
        // Nielsen (on end)
        if (window.location.hostname.match(/nba\.com$/)) {
            var imgSrc = 'http://secure-us.imrworldwide.com/cgi-bin/m?ci=us-100429&tl=dav2-' +
            encodeURIComponent(media.getTitle()) +
            '&c6=vc,c08&cc=1&rnd=' +
            Math.ceil(Math.random() * 1000000000);
            this._log.debug("Sending Nielsen tracking call for stream end: " + imgSrc);
            img = new Image();
            img.src = imgSrc;
        }
        else {
            this._log.info("Ignoring Nielsen tracking call for view from: " + window.location.hostname);
        }
        
		// other tracking pings for video content
		if (media.isVideo()) {
			// searchignite.com video-end
			var siimage = new Image(); 
			siimage.src = 'http://track.searchignite.com/si/CM/Tracking/TransactionTracking.aspx?siclientid=3114&transactionamount=0&SICustTransType=12680&jscript=0&rnd=' + Math.ceil(Math.random() * 1000000000);
			this._log.info('Sending searchignite.com tracking call for video start: \n' + siimage.src);

		}

        return true;
    },
    
    // Handles the nth segment of a stream
    // Triggers a micro call
    onSegmentStart: function(media, n){
        this._log.info("A stream segment event was received for segment #" + n + " of video: [ " + media.toString() + "]");
        this._log.info("UnsupportedOperation: EventHandler.onSegmentStart has not been implemented. No data will be tracked for this event. You can ignore this message.");
        return true;
    },
    
    // Handles an attempt to view a stream that is blacked out
    // Triggers a micro call
    onBlackout: function(media){
        this._log.info("A blackout event was received for media: [" + media.toString() + "]");
        if (!this._isValidMedia(media) || media.getType() != Media.TYPE.LPMedia) {
            this._log.error("Media object was invalid. Unfortunately, Omniture cannot continue. Invalid media: " + media.toString());
            return false;
        }
        var s = s_gi(s_account);
        s.linkTrackVars = "prop1,prop2,prop3,prop4,prop5,prop6,prop7,eVar1,eVar2,eVar3,eVar4,eVar5,eVar7,eVar9,eVar10,eVar11,events";
        s.linkTrackEvents = "event5";
        this._prepVars(s);
        s.prop4 = media.getId();
        s.prop5 = media.getTitle();
        s.prop6 = media.getType();
        s.prop7 = media.getTitle();
        s.eVar4 = media.getId();
        s.eVar5 = media.getTitle();
        s.eVar7 = media.getMode();
        s.eVar9 = media.getHomeTeam();
        s.eVar10 = media.getVisitingTeam();
        s.eVar11 = media.getMatchup();
        this._queue("event5");
        s.tl(true, 'o', "EventHandler.onBlackout");
        this._clearQueue();
        return true;
    },
    
    _onRegistrationStart: function(){
        var s = s_gi(s_account);
        s.linkTrackVars = "prop1,prop2,prop3,eVar1,eVar2,eVar3,eVar14,events";
        s.linkTrackEvents = this.getQueue();
        this._prepVars(s);
        s.tl(this, 'o', "EventHandler.onRegistrationStarted");
        this._clearQueue();
        return true;
    },
    
    _onRegistrationComplete: function(){
        var s = s_gi(s_account);
        s.linkTrackVars = "prop1,prop2,prop3,eVar1,eVar2,eVar3,eVar14,events";
        s.linkTrackEvents = this.getQueue();
        this._prepVars(s);
        s.tl(this, 'o', "EventHandler.onRegistrationComplete");
        this._clearQueue();
        return true;
    },
    
    _onFlowStart: function(){
        var s = s_gi(s_account);
        s.linkTrackVars = "prop1,prop2,prop3,eVar1,eVar2,eVar3,eVar13,events";
        s.linkTrackEvents = this.getQueue();
        this._prepVars(s);
        s.tl(this, 'o', "EventHandler.onFlowStart");
        this._clearQueue();
        return true;
    },
    
    _onFlowComplete: function(){
        var s = s_gi(s_account);
        s.linkTrackVars = "prop1,prop2,prop3,eVar1,eVar2,eVar3,eVar13,events";
        s.linkTrackEvents = this.getQueue();
        this._prepVars(s);
        s.tl(this, 'o', "EventHandler.onFlowComplete");
        this._clearQueue();
        return true;
    },
    
    _onOrderStart: function(){
        var s = s_gi(s_account);
        s.linkTrackVars = "prop1,prop2,prop3,eVar1,eVar2,eVar3,eVar8,eVar13,events,products";
        s.linkTrackEvents = this.getQueue();
        this._prepVars(s);
        s.tl(this, 'o', "EventHandler.onOrderStart");
        this._clearQueue();
        return true;
    },
    
    
    
    /**** MACRO-TRACKING BASED CALLBACKS ****/
    
    
    onFlowStart: function(flowName, micro){
        this._log.info("Adding 'Flow Start' event to queue for flow: " + flowName);
        this._queue("event1");
        window.$_om_flowName = flowName;
        if (micro) {
            return this._onFlowStart();
        }
        else {
            return true;
        }
    },
    
    onFlowComplete: function(flowName, micro){
        this._log.info("Adding 'Flow Complete' event to queue for flow: " + flowName);
        this._queue("event2");
        window.$_om_flowName = flowName;
        if (micro) {
            return this._onFlowComplete();
        }
        else {
            return true;
        }
    },
    
    onRegistrationStart: function(regTarget, regType, micro){
        this._log.info("A 'Registration Start' event was received with target: [" + regTarget + "] and type: [" + regType + "].");
        this._queue("event9");
        window.$_om_regTarget = regTarget;
        window.$_om_regType = regType;
        if (micro) {
            return this._onRegistrationStart();
        }
        else {
            return true;
        }
    },
    
    onRegistrationComplete: function(regTarget, regType, micro){
        this._log.info("A 'Registration Complete' event was received with target: [" + regTarget + "] and type: [" + regType + "].");
        this._queue("event10");
        window.$_om_regTarget = regTarget;
        window.$_om_regType = regType;
        if (micro) {
            return this._onRegistrationComplete();
        }
        else {
            return true;
        }
    },
    
    // Accepts and handles any number of arguments
    onSplashView: function(){
        this._log.info("Adding 'Splash View' event to queue");
        this._queue("prodView");
        this._setProducts(arguments);
        return true;
    },
    
    onOrderStart: function(products, micro){
        if (products && products.length > 0) {
            this._log.info("Adding 'Begin Order Process' event to queue");
            this.onFlowStart("LeaguePass-Order");
            this._queue("scAdd");
            this._setProducts(products);
            if (micro) {
                return this._onOrderStart();
            }
            else {
                return true;
            }
        }
        else {
            this._log.error("No products were provided. Unfortunately, Omniture cannot continue.");
            return false;
        }
    },
    
    onCheckoutStart: function(products){
        if (products && products.length > 0) {
            this._log.info("Adding 'Begin Checkout Process' event to queue");
            this._queue("scCheckout");
            this._setProducts(products);
            return true;
        }
        else {
            this._log.error("No products were provided. Unfortunately, Omniture cannot continue.");
            return false;
        }
    },
    
    // Accepts and handles any number of arguments
    onOrderComplete: function(products){
        if (products && products.length > 0) {
            this._log.info("Adding 'Order Complete' event to queue")
            this.onFlowComplete("LeaguePass-Order");
            this._queue("purchase");
            this._setProducts(products);
            return true;
        }
        else {
            this._log.error("No products were provided. Unfortunately, Omniture cannot continue.");
            return false;
        }
    },
    
    getQueue: function(){
        return this._q.join(",");
    },
    
    _setProducts: function(p){
        var o = "";
        if (p && p.constructor == String) {
            if (p.indexOf(',') > 0) 
                p = p.split(',');
            else 
                if (p.indexOf(';') > 0) 
                    p = p.split(';');
                else 
                    p = [p];
        }
        if (p && p.constructor == Number) {
            p = [p + ''];
        }
        if (p && p.constructor == Object) {
            var a = new Array();
            for (var i = 0; i < p.length; i++) {
                a.push(p[i]);
            }
            p = a;
        }
        if (p && p.constructor == Array) {
            for (var i = 0; i < p.length; i++) {
                o += ";" + p[i] + ";;";
                if ((i + 1) < p.length) 
                    o += ",";
            }
        }
        if (o) 
            window.$_om_products = o;
    },
    
    _queue: function(e){
        for (var i = 0; i < this._q.length; i++) {
            if (e.toLowerCase() == this._q[i].toLowerCase()) {
                this._log.warn("Duplicate event [" + e + "] was discarded and NOT added to queue a second time");
                return;
            }
        }
        this._q.push(e);
        this._log.debug("Added event [" + e + "] to queue");
        this._log.debug("Current event queue: " + this._q.join(", "));
    },
    
    _clearQueue: function(){
        this._log.debug("Clearing event queue");
        this._q = new Array();
    },
    
    _prepVars: function(s){
        var v = s.linkTrackVars.split(",");
        for (var i = 0; i < v.length; i++) {
            s[v[i]] = "";
        }
    },
    
    _isValidMedia: function(media){
    
        return true;
    }
};

function handleStreamStart(id, title, homeTeam, visitingTeam, mode, live, cdn, bitrate){
    try {
        var v = new Media.LPMedia({
            id: id,
            title: title,
            homeTeam: homeTeam,
            visitingTeam: visitingTeam,
            mode: mode,
            delivery: live,
            cdn: cdn,
            bitrate: bitrate
        });
        return EventHandler.onStreamStart(v);
    } 
    catch (e) {
        return false;
    }
}

function handleStreamEnd(id, title, homeTeam, visitingTeam, mode, live, cdn, bitrate){
    try {
        var v = new Media.LPMedia({
            id: id,
            title: title,
            homeTeam: homeTeam,
            visitingTeam: visitingTeam,
            mode: mode,
            delivery: live,
            cdn: cdn,
            bitrate: bitrate
        });
        return EventHandler.onStreamEnd(v);
    } 
    catch (e) {
        return false;
    }
}

function handleSegmentStart(id, title, homeTeam, visitingTeam, mode, live, cdn, bitrate, n){
    try {
        var v = new Media.LPMedia({
            id: id,
            title: title,
            homeTeam: homeTeam,
            visitingTeam: visitingTeam,
            mode: mode,
            delivery: live,
            cdn: cdn,
            bitrate: bitrate
        });
        return EventHandler.onSegmentStart(v, n);
    } 
    catch (e) {
        return false;
    }
}

function handleBlackout(id, title, homeTeam, visitingTeam, mode, live){
    try {
        var v = new Media.LPMedia({
            id: id,
            title: title,
            homeTeam: homeTeam,
            visitingTeam: visitingTeam,
            mode: mode,
            delivery: live
        });
        return EventHandler.onBlackout(v);
    } 
    catch (e) {
        return false;
    }
}

/**
 * Simple callback for Flash, wrapping the native Media objects.
 * Called when the video stream begins playing.
 *
 * @param {String} id		Unique video identifier				"/video/channels/top_plays/2008/12/04/nba_20081203_zap.nba"
 * @param {String} title	Display-friendly title of video		"The Daily Zap"
 * @param {String} category	CMS category of video				"/video/top_plays"
 * @param {Number} bitrate	Bitrate, in kb, of the stream		500
 */
function handleEVPStreamStart(id, title, category, bitrate){
    try {
        var v = new Media.EVPMedia({
            id: id,
            title: title,
            category: "",
            bitrate: bitrate
        });
        return EventHandler.onStreamStart(v);
    } 
    catch (e) {
        return false;
    }
}

/**
 * Simple callback for Flash, wrapping the native Media objects.
 * Called when the video stream reaches its natural end.
 *
 * @param {String} id		Unique video identifier				"/video/channels/top_plays/2008/12/04/nba_20081203_zap.nba"
 * @param {String} title	Display-friendly title of video		"The Daily Zap"
 * @param {String} category	CMS category of video				"/video/top_plays"
 * @param {Number} bitrate	Bitrate, in kb, of the stream		500
 */
function handleEVPStreamEnd(id, title, category, bitrate){
    try {
        var v = new Media.EVPMedia({
            id: id,
            title: title,
            category: "",
            bitrate: bitrate
        });
        return EventHandler.onStreamEnd(v);
    } 
    catch (e) {
        return false;
    }
}

/**
 * Simple callback for Flash, wrapping the native Media objects.
 * Called when the video stream reaches its halfway point.
 *
 * @param {String} id		Unique video identifier				"/video/channels/top_plays/2008/12/04/nba_20081203_zap.nba"
 * @param {String} title	Display-friendly title of video		"The Daily Zap"
 * @param {String} category	CMS category of video				"/video/top_plays"
 * @param {Number} bitrate	Bitrate, in kb, of the stream		500
 * @param {String} n		Name or number of segment			"#midpoint"
 */
function handleEVPSegmentStart(id, title, category, bitrate, n){
    try {
        var v = new Media.EVPMedia({
            id: id,
            title: title,
            category: "",
            bitrate: bitrate
        });
        return EventHandler.onSegmentStart(v, n);
    } 
    catch (e) {
        return false;
    }
}

