/**
 * DPC GA for Youtube Embed
 *
 * http://directperformance.com.br/
 *
 *  Copyright 2010 Direct Performance
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 * $Date: 2009-10-01 17:52:42 -0300 (qui, 01 out 2009) $
 * @fileoverview  Library to track youtube embedded video interactions using Google Analytics
 * @author DirectPerformance -  http://www.directperformance.com.br/ <contato@directperformance.com.br>
 * @version $Revision$
 *
 */

var YoutubeTrackerGlobal = window.YoutubeTrackerGlobal = {};
YoutubeTrackerGlobal.bucket_ = [];
YoutubeTrackerGlobal.objects = [];
YoutubeTrackerGlobal.timeout = -1;
YoutubeTrackerGlobal.seekTimeout = -1;
YoutubeTrackerGlobal.callbackTracker = function(video_code,action,bucket,time_seconds){};

 /**
 * @class Youtube Tracking Component
 * This class encapsulates all logic for tracking youtube videos on a page
 * To track Embedded Youtube Videos:
 * 1) Specify  a ID for the OBJECT or EMBED tag
 *     Ex: <object id="myytplayer"> or <embed id="myytplayer">
 * 2) Include Youtube JS API parameters in OBJECT or EMBED url: &enablejsapi=1&playerapiid=ytplayer
 *     Ex: http://www.youtube.com/v/gRvUpoTT-Bo&hl=pt-br&fs=1&enablejsapi=1&playerapiid=myytplayer
 * 3) Specify atributo allowscriptaccess="always"
 *     Ex: <param name="allowscriptaccess" value="always"> or <embed allowscriptaccess="always">
 * @param {Number[]} [arg1=[10, 30, 60, 180, 600]] Array that represents the bucket
 * @constructor
 */
var YoutubeTracker = window.YoutubeTracker = function(opt_bucket,callback,debug) {
  if (opt_bucket) {
    YoutubeTrackerGlobal.bucket_ = opt_bucket.sort(YoutubeTrackerGlobal.sortNumber);
  } else {
    YoutubeTrackerGlobal.bucket_ = YoutubeTracker.DEFAULT_BUCKET;
  }
  if (callback){
        YoutubeTrackerGlobal.callbackTracker = callback;
  } else {
        try{
                YoutubeTrackerGlobal.callbackTracker = _gat._getTrackerByName()._trackEvent;
        }catch(e){
                YoutubeTrackerGlobal.callbackTracker = pageTracker._trackEvent;
        }
  }
  if (debug){
        YoutubeTrackerGlobal.callbackTracker_ = YoutubeTrackerGlobal.callbackTracker;
        YoutubeTrackerGlobal.callbackTracker = function(video_code,action,bucket,time_seconds){
                YoutubeTrackerGlobal.callbackTracker_(video_code,action,bucket,time_seconds);
                if (typeof console != 'undefined'){
                        if (console&&console.log){
                                console.log(video_code + ', ' + action + ', ' + bucket + ', ' + time_seconds);//DEBUG
                        }
                }
        };
  }
};

/**
 * Helper function to sort an Array of numbers
 * @public
 * @param {Number} arg1 The first number
 * @param {Number} arg2 The second number
 * @return The difference used to sort
 * @type Number
 */
YoutubeTrackerGlobal.sortNumber = function(a, b) {
  return (a - b);
};

/**
 * Sets the bucket for histogram generation in GA
 * @public
 * @param {Number[]} The bucket array
 */
YoutubeTrackerGlobal._setHistogramBuckets = function(buckets_array) {
  YoutubeTrackerGlobal.bucket_ = buckets_array.sort(this.sortNumber);
};


/**
 * @constant
 * */
YoutubeTracker.DEFAULT_BUCKET = [10, 30, 60, 180, 600];

/**
 * Get the current bucket for a given time in seconds
 * @public
 * @param {Number[]} The bucket array
 */
YoutubeTrackerGlobal.getBucket = function(time){
        var i;
        var bucketString;
        //if (time==0) return "0";
        for(i = 0; i < YoutubeTrackerGlobal.bucket_.length; i++) {
                if (time < YoutubeTrackerGlobal.bucket_[i]) {
                        if (i === 0) {
                                bucketString = "0-" + (YoutubeTrackerGlobal.bucket_[0]);
                                break;
                        } else {
                                bucketString = YoutubeTrackerGlobal.bucket_[i - 1] + "-" + (YoutubeTrackerGlobal.bucket_[i] - 1);
                                break;
                        }
                }
        }
        if (!bucketString) {
                bucketString = YoutubeTrackerGlobal.bucket_[i - 1] + "+";
        }
        return bucketString;
};

/**
 * Sends a event with the maximum time viewed for each video on the page
 * @public
 */
YoutubeTrackerGlobal.trackMaxTime = function(){
        var bucketString, cat_name, action_name, ytplayer;
        for (var i in YoutubeTrackerGlobal.objects){
                if (YoutubeTrackerGlobal.objects[i]){
                        bucketString = YoutubeTrackerGlobal.getBucket(YoutubeTrackerGlobal.objects[i].maxTime);
                        ytplayer = document.getElementById(YoutubeTrackerGlobal.objects[i].id);
                        if (ytplayer){
                                cat_name = ytplayer._YoutubeTracker_videoId();
                                action_name = "max-time";
                                YoutubeTrackerGlobal.callbackTracker(cat_name,action_name,bucketString,YoutubeTrackerGlobal.objects[i].maxTime);
                        }
                }
        }
};

/**
 * Update all the current status and time values for all the video objects
 * @public
 */
YoutubeTrackerGlobal.updatetimer = function(){
        var currTime, ytplayer, cat_name, action_name, actualBucket;
        for (var i in YoutubeTrackerGlobal.objects){
                if (YoutubeTrackerGlobal.objects[i]){
                        ytplayer = document.getElementById(YoutubeTrackerGlobal.objects[i].id);
                        if (ytplayer&&ytplayer.getCurrentTime){
                                currTime = parseInt(ytplayer.getCurrentTime(),10);
                                ytplayer._YoutubeTracker_last_posicao = currTime;
                                if (currTime>YoutubeTrackerGlobal.objects[i].maxTime) {YoutubeTrackerGlobal.objects[i].maxTime = currTime;}
                                //check if viewing time changes the bucket while playing
                                if (ytplayer.getPlayerState()==1){
                                        actualBucket = YoutubeTrackerGlobal.getBucket(currTime);
                                        if (actualBucket!=ytplayer._YoutubeTracker_lastBucket){
                                                cat_name = ytplayer._YoutubeTracker_videoId();
                                                action_name = "view-range";
                                                YoutubeTrackerGlobal.callbackTracker(cat_name,action_name,actualBucket,currTime);
                                                ytplayer._YoutubeTracker_lastBucket = actualBucket;
                                        }
                                }
                        }
                }
        }
};

/**
 * Captures Youtube JS API Event
 * @public
 * @playerId {String[]}  Object ID passed in &playerapiid
 */
if (typeof onYouTubePlayerReady != 'undefinded') window.onYouTubePlayerReady_original = window.onYouTubePlayerReady; // stores original custom events
window.onYouTubePlayerReady = function(playerId) {
        if (typeof window.onYouTubePlayerReady_original != 'undefinded') window.onYouTubePlayerReady_original(playerId);
        //video identification
        var ytplayer = document.getElementById(playerId);
        //method to send video actions
        if (ytplayer){
                ytplayer._YoutubeTracker_videoId = function(){
                        re = /(v=|v\/|p\/)([^&?]+)/.exec(this.getVideoUrl());
                        url_video=((re&&re[2])?re[2]:this.getVideoUrl())||this.getVideoUrl();
                        return "youtube-video:" + url_video;
                }
                YoutubeTrackerGlobal.objects.push({id:playerId,maxTime:0,cod:ytplayer._YoutubeTracker_videoId()});
                ytplayer._YoutubeTracker_sendaction = function(newState){
                        var cat_name = this._YoutubeTracker_videoId();
                        posicao = parseInt(this.getCurrentTime(),10);
                        var action_name = newState;
                        switch (newState){
                                case -1: action_name="nunstarted"; break;
                                case 0: action_name="ended"; break;
                                case 1: action_name="playing";break;
                                case 2: action_name="paused";break;
                                case 3: action_name="buffering"; break;
                                case 5: action_name="cued"; break;
                        }
                        //detect rewind and forward
                        if (posicao<(ytplayer._YoutubeTracker_last_posicao-1)){
                                action_name="rewind";
                        }else if(posicao>(ytplayer._YoutubeTracker_last_posicao+1)){
                                action_name="fast-forward";
                        }
                        //detect rewind and forward after paused
                        var seekAfterPause = false;
                        if (action_name=="playing"){
                                if (posicao<(ytplayer._YoutubeTracker_last_posicao_paused-1)){
                                        action_name="rewind";
                                        seekAfterPause = true;
                                }else if(posicao>(ytplayer._YoutubeTracker_last_posicao_paused+1)){
                                        action_name="fast-forward";
                                        seekAfterPause = true;
                                }
                        }
                        //don't track buffering state (3) or repeated events
                        if ((action_name!="buffering")&&(action_name!=ytplayer._YoutubeTracker_last_action)){
                                ytplayer._YoutubeTracker_last_action = action_name;
                                var last_posicao_ = ytplayer._YoutubeTracker_last_posicao;
                                if (seekAfterPause){ last_posicao_ = ytplayer._YoutubeTracker_last_posicao_paused;}
                                ytplayer._YoutubeTracker_last_posicao = posicao;
                                var bucketString;
                                //avoid track paused if its just used to track seeking events
                                if (action_name=="paused"){
                                        ytplayer._YoutubeTracker_last_posicao_paused = posicao;
                                        bucketString = YoutubeTrackerGlobal.getBucket(posicao);
                                        YoutubeTrackerGlobal.seekTimeout = setTimeout("YoutubeTrackerGlobal.callbackTracker('"+cat_name+"','"+action_name+"','"+bucketString+"',0"+posicao+");",300);
                                } else {
                                        //seeking events
                                        if ((action_name=="rewind")||(action_name=="fast-forward")){
                                                clearTimeout(YoutubeTrackerGlobal.seekTimeout); //cancel previou paused events
                                                //track both from and to positions for seeking events
                                                bucketString = YoutubeTrackerGlobal.getBucket(last_posicao_);
                                                YoutubeTrackerGlobal.callbackTracker(cat_name,action_name+':from',bucketString,last_posicao_);
                                                bucketString = YoutubeTrackerGlobal.getBucket(posicao);
                                                YoutubeTrackerGlobal.callbackTracker(cat_name,action_name+":to",bucketString,posicao);
                                        } else {
                                                // other events
                                                bucketString = YoutubeTrackerGlobal.getBucket(posicao);
                                                YoutubeTrackerGlobal.callbackTracker(cat_name,action_name,bucketString,posicao);
                                        }
                                }
                        }
                };
                ytplayer.addEventListener("onStateChange", "document.getElementById('"+playerId+"')._YoutubeTracker_sendaction");
                //error handling
                ytplayer._YoutubeTracker_senderror = function(errCode){
                        var cat_name = this._YoutubeTracker_videoId();
                        YoutubeTrackerGlobal.callbackTracker(cat_name,"error",errCode);
                };
                ytplayer.addEventListener("onError", "document.getElementById('"+playerId+"')._YoutubeTracker_senderror");
        }
        // updates position each second
        YoutubeTrackerGlobal.timeout = setInterval(YoutubeTrackerGlobal.updatetimer,500);
};
