// Copyright 2007 Google, Inc.
// This sample code is under the Apache2 license, see
// http://www.apache.org/licenses/LICENSE-2.0 for license details.

/**
 * @fileoverview Wrapper for Time Tracking
 */

/**
 * @class Time Tracking component.
 *     This class encapsulates all logic for time tracking on a particular
 *     page. Time tracking could be for any object within a page or the page
 *     itself.
 *
 * @param {Array.<Number>} arg1 Optional array that represents the bucket
 * @constructor
 */
var TimeTracker = function(opt_bucket) {
	if (opt_bucket) {
		this.bucket_ = opt_bucket.sort(this.sortNumber); 
	} else {
		this.bucket_ = TimeTracker.DEFAULT_BUCKET;
	}
};

TimeTracker.prototype.startTime_;
TimeTracker.prototype.stopTime_;
TimeTracker.prototype.bucket_;
TimeTracker.DEFAULT_BUCKET = [100, 500, 1500, 2500, 5000];

/**
 * Calculates time difference between start and stop
 * @return {Number} The time difference between start and stop
 */
TimeTracker.prototype._getTimeDiff = function() {
	return (this.stopTime_ - this.startTime_);
};

/**
 * Helper function to sort an Array of numbers
 * @param {Number} arg1 The first number
 * @param {Number} arg2 The second number
 * @return {Number} The difference used to sort
 */
TimeTracker.prototype.sortNumber = function(a, b) {
	return (a - b);
}

/**
 * Records the start time
 * @param {Number} arg1 Optional start time specified by user
 */
TimeTracker.prototype._recordStartTime = function(opt_time) {
	if (opt_time != undefined) {
		this.startTime_ = opt_time;
	} else {
		this.startTime_ = (new Date()).getTime();
	}
};

/**
 * Records the stop time
 * @param {Number} arg1 Optional stop time specified by user
 */
TimeTracker.prototype._recordEndTime = function(opt_time) {
	if (opt_time != undefined) {
		this.stopTime_ = opt_time;
	} else {
		this.stopTime_ = (new Date()).getTime();
	}
};

/**
 * Tracks the event. Calculates time and sends information to
 * the event tracker passed
 * @param {Object} arg1 GA tracker created by user
 * @param {String} arg2 Optional event category
 * @param {String} arg3 Optional event label
 */
TimeTracker.prototype._track = function(tracker,
										opt_event_category,
                                        opt_event_label,
                                        opt_page) {

    var i;
    var bucketString;
    var category;
    var page;

    if (opt_event_category != undefined && opt_event_category.length != 0) {
        category = opt_event_category;
    } else {
        category = 'TimeTracker';
    }

    if (opt_event_label != undefined && opt_event_label.length != 0) {
        page = opt_event_label;
    } else {
        page = 'Page';
    }

    for (i = 0; i < this.bucket_.length; i++) {
        if ((this._getTimeDiff()) < this.bucket_[i]) {
            if (i == 0) {
                bucketString = "0-" + (this.bucket_[0]);
                break;
            } else {
                bucketString = this.bucket_[i - 1] + "-" + (this.bucket_[i] - 1);
                break;
            }
        }
    }
    if (!bucketString) {
        bucketString = this.bucket_[i - 1] + "+";
    }

    try {
        if (this._getTimeDiff() < 60000) {  /* Only record events less than a minute */
            tracker._trackEvent(category, opt_page, opt_event_label, this._getTimeDiff());
        }
    } catch (e) { }
};

/**
 * Sets the bucket for histogram generation in GA
 * @param {Array.<Number>} The bucket array
 */
TimeTracker.prototype._setHistogramBuckets = function(buckets_array) {
	this.bucket_ = buckets_array.sort(this.sortNumber);
};

/*=========================================================================*/

/**
* @class Page Load Tracking component.
*     This class encapsulates all logic for page load time tracking on a particular
*     page. 
*
* @param {String} arg1 Variable name of the Google Analytics tracking object used on the page
* @param {String} arg2 Optional page name of index page
* @param {Number} arg3 Optional start time specified by user
* @constructor
*/

var PageLoadTracker = function(GATrackerObj, defaultPage, startTime) {
    this.GATrackerObj_ = GATrackerObj;
    this.defaultPage_ = defaultPage;
    this.timeTracker_ = new TimeTracker(PageLoadTracker.DEFAULT_BUCKET);
    this.timeTracker_._recordStartTime(startTime);
};

PageLoadTracker.prototype.GATrackerObj_;
PageLoadTracker.prototype.defaultPage_;
PageLoadTracker.prototype.timeTracker_;
PageLoadTracker.DEFAULT_BUCKET = [1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000, 9000, 10000, 15000, 20000];

/**
*  Determines what page name to send as the event label, and sends the event tracking request
*/
PageLoadTracker.prototype.track = function() {

    var GATrackerObj = null;
    var pageName = "";

    if (window.location.pathname.search(/\/$/) >= 0)
        pageName = window.location.pathname + this.defaultPage_;
    else
        pageName = window.location.pathname;

    if (window[this.GATrackerObj_] != 'undefined')
        GATrackerObj = window[this.GATrackerObj_];
    else if (document[this.GATrackerObj_] != 'undefined')
        GATrackerObj = document[this.GATrackerObj_];

    if (GATrackerObj != null && typeof GATrackerObj == 'object') {
        try {
            this.timeTracker_._recordEndTime();
            this.timeTracker_._track(GATrackerObj, 'PageLoadTimes', pageName, this.defaultPage_);
        } catch (e) { }
    }
};

/**
*  Adds event handler for specified event to an element
*  
*  @param	element	Element to add event listener to
*  @param	type		Event to listen for.  Do not prepend event with 'on', as the functions automatically prepends it
*  @param	expression	Javascript function to execute on event.  Can be either a function name or anonymous function
*  @param	bubbling	Sets whether to register the event on bubbling phase (true) or capturing phase (false).  Only applies to W3C compliant browsers.
*  @return			True on success, false on failure
*/
function addListener(element, type, expression, bubbling) {
    bubbling = bubbling || false;

    if (window.addEventListener) { // Standard
        element.addEventListener(type, expression, bubbling);
        return true;
    } else if (window.attachEvent) { // IE
        element.attachEvent('on' + type, expression);
        return true;
    } else return false;
}
