﻿(function ($)
{
    if (typeof kwwika == "undefined")
    {
        return;
    }

    kwwika.namespace("kwwika.jQuery");

    kwwika.jQuery.AttrUpdater = function (aSelectedEls, oConfig)
    {
        this.version = "0.1";
        this.author = "Phil Leggetter";
        this.authorEmail = "phil@kwwika.com";

        var oThis = this;
        this.m_oConfig = $.extend({
            apiKey: null,
            topicAttr: "data-topic",
            fieldAttr: "data-field",
            transformAttr: "data-transform",
            transform: function () { return oThis.transform.apply(oThis, arguments); },
            log: function () { oThis.log.apply(oThis, arguments); },
            debug: false
        }, oConfig || {});

        this.m_oConnection = kwwika.Service.connect(this);
        this.m_mTopicsToSubscribeTo = {};

        var sTopicName;
        var aEls = aSelectedEls.find("*[" + oThis.m_oConfig.topicAttr + "]");
        aEls = aEls.add( aSelectedEls.filter("*[" + oThis.m_oConfig.topicAttr + "]") );
        aEls.each(function (nIndex, oEl)
        {
            oEl = $(oEl);
            sTopicName = oEl.attr(oThis.m_oConfig.topicAttr);
            oThis.m_mTopicsToSubscribeTo[sTopicName] = oThis.m_oConnection.subscribe(sTopicName, oThis);
        });
    };

    /**
    * default logger - try to output to the console if in debug mode.
    */
    kwwika.jQuery.AttrUpdater.prototype.log = function (sMsg)
    {
        if (this.m_oConfig.debug)
        {
            if (window.console)
            {
                console.debug(sMsg);
            }
            else
            {
                alert(sMsg);
            }
        }
    };

    /**
    * Default transform handler - do nothing.
    */
    kwwika.jQuery.AttrUpdater.prototype.transform = function (sTopicName, sFieldName, sValue)
    {
        return sValue;
    };

    /**
    * standard connection status callback.
    */
    kwwika.jQuery.AttrUpdater.prototype.connectionStatusUpdated = function (sStatus)
    {
        this.m_oConfig.log("connectionStatusUpdated: " + sStatus);
    };

    /**
    * handle data update.
    */
    kwwika.jQuery.AttrUpdater.prototype.topicUpdated = function (oSub, mUpdate)
    {
        var oThis = this;
        this.m_oConfig.log("topicUpdated for: " + oSub.topicName);

        var aElsToUpdate = $("*[" + this.m_oConfig.topicAttr + "=" + oSub.topicName + "]");

        this.m_oConfig.log("Found " + aElsToUpdate.size() + " elements for topic " + oSub.topicName);

        for (var sField in mUpdate)
        {
            var sValue = mUpdate[sField];

            oThis.m_oConfig.log("found field " + sField + " in mUpdate with value " + sValue);

            var aElsForFieldAndTopic = aElsToUpdate.filter("[" + oThis.m_oConfig.fieldAttr + "=" + sField + "]");

            this.m_oConfig.log("Found " + aElsForFieldAndTopic.size() + " elements for topic " + oSub.topicName + " and field " + sField);

            aElsForFieldAndTopic.each(function (nIndex, oUpdateEl)
            {
                oUpdateEl = $(oUpdateEl);
                var sTransformFunctionName = oUpdateEl.attr(oThis.m_oConfig.transformAttr);

                oThis.m_oConfig.log("Transform attribute for el: " + sTransformFunctionName);

                var fTransform = (typeof window[sTransformFunctionName] == "function" ? window[sTransformFunctionName] : oThis.m_oConfig.transform);
                var sTransformedValue = fTransform(oSub.topicName, sField, sValue);

                oThis.m_oConfig.log("Value before transform: " + sValue + " value after transform " + sTransformedValue);

                oUpdateEl.html(sTransformedValue);
            });
        }
    };

    kwwika.jQuery.AttrUpdater.prototype.topicError = function (oSub, sError)
    {
        this.m_oConfig.log("Error subscribing to " + oSub.topicName + " Reason: " + sError);
    };

    $.fn.kwwika = function (oOptions)
    {
        var oUpdater = new kwwika.jQuery.AttrUpdater(this, oOptions);
        return oUpdater;
    };

})(jQuery);