﻿/* An analytics engine used to track and submit analytics events. */
function AnalyticsEngine(interval) {

    var eventBuffer = [];   // A buffer to hold events
    var intervalID = null;  // The ID of the running interval


    /* Start the analytics submissions on the configured interval.
       Return false if it couldn't be started because it's already running
       or doesn't have a useful interval configured. */
    this.Start = function (newInterval) {

        if (!intervalID) {

            if (newInterval) {
                interval = newInterval;
            }

            if (interval > 0) {
                intervalID = window.setInterval(submitAllEvents, interval);
                return true;
            }
        }
        return false;
    };


    /* Stop the analytics submissions.
       Return false if it couldn't be stopped (probably because it wasn't running). */
    this.Stop = function (submit) {

        // Submit any events waiting in the buffer
        if (submit) {
            submitAllEvents();
        }

        // Clear the running interval
        if (intervalID) {
            window.clearInterval(intervalID);
            intervalID = null;
            return true;
        }

        return false;
    };


    /* Check to see if analytics submissions are running. */
    this.IsRunning = function () {
        return !!intervalID;
    };


    /* Track an AnalyticsEvent.
       Return false if the event is not a proper AnalyticsEvent. */
    this.TrackEvent = function (event) {

        if (event && event instanceof AnalyticsEvent) {

            if (interval > 0) {
                // Put the event in the buffer if we have an interval
                eventBuffer.push(event);
            } else {
                // Otherwise, submit the event as soon as is convenient
                window.setTimeout(function () {submitEvent(event);}, 0);
            }

            return true;
        }
        return false;
    };


    /* Submit the passed event. */
    var submitEvent = function (event) {
        if (MV.WebServices.Analytics.LogAnalyticsEvent) {
            MV.WebServices.Analytics.LogAnalyticsEvent(event.GetWebServiceParameters());
        }
    };


    /* Submit all the events waiting in the buffer, return the number of events submitted. */
    var submitAllEvents = function () {
        var numEvents = eventBuffer.length;
        for (var i = 0; i < numEvents; i++) {
            submitEvent(eventBuffer[i]);
        }
        eventBuffer = [];
        return numEvents;
    };


    /* Track the end session event and stop the Engine. */
    var unload = function () {
        this.TrackEvent(new ApplicationUnloadEvent());
        this.Stop(true);
    };
    // This binds to the window unload, but isn't reliable.
    // $(window).bind('unload', unload);
};



/* An object to encapsulate a generic event to be logged in web analytics. */
function AnalyticsEvent(type, parameters) {

    // The salient parameters for the event.
    parameters = parameters || {};

    parameters.client = Config.Analytics.Client;
    parameters.version = Config.Analytics.Version;

    /* Gets a parameter's value. */
    this.GetParameter = function (name) {
        return parameters[name];
    };


    /* Sets a new parameter, return false if a proper name/value pair is missing. */
    this.SetParameter = function (name, value) {
        if (name && value) {
            parameters[name] = value;
            return true;
        }
        return false;
    };


    /* Remove a parameter, return its value or false if it wan't found in the event. */
    this.RemoveParameter = function (name) {
        if (name && parameters[name]) {
            var value = parameters[name];
            delete parameters[name];
            return value;
        }
        return false;
    };


    /* Return the parameters in an object that the framework's BaseWebService expects. */
    this.GetWebServiceParameters = function () {
        var wsParameters = ['eventType', type]
        for (var name in parameters) {
            var value = parameters[name];
            wsParameters.push(name, value);
        }
        return wsParameters;

        /* old way
        return {
            ObjectName: type,
            Parameters: wsParameters
        };
        */
    };


    /* Return the CGI parameters in an object. */
    this.GetCGIParameters = function () {
        var cgiParameters = {};
        cgiParameters['type'] = type;

        for (var name in parameters) {
            cgiParameters[name] = parameters[name];
        }

        return cgiParameters;
    };


    /* Override Object.toString(). */
    this.toString = function () {

        // An array to hold string bits
        var stringArray = ['{\n\t'/* , '"type":"', type, '"' */];

        for (var name in parameters) {
            var value = parameters[name];
            if (typeof value === "string") {
                if (value === "") {
                    value = null;
                }
                else {
                    // TODO: escape quotes etc to make valid JSON
                    value = '"' + value + '"';
                }
            }
            stringArray.push(',\n\t"', name, '":', value);
        }

        stringArray.push('\n}');
        return stringArray.join();
    };


    /* Override Object.valueOf(). */
    this.valueOf = function () {
        return this.toString();
    };
}
