var SMLog = null;
jQuery(document).ready(function($) {

    /*
        Toggle button for displaying/hiding subnodes of a category keyword node.
    */

    SMLog = new DNLog('.dashnex-log__container');

    $('body').on('click', '.fa-toggleIcon', function() {
        $(this).closest('.ptm-toggle').next('.ptm-toggleContent').slideToggle('fast');
        $(this).toggleClass('fa-plus-square-o');
        $(this).toggleClass('fa-minus-square-o');
    });

    // Legend Popover
    $('.legend__item .fa').popover();

    $('.ptm-result__heading .dnc-sm-action').popover();

    /*
        Dismissing WP admin notices by clicking on them.
    */

    $('body').on('click', '.dnc-fade', function() {
        $(this).fadeOut();
    });

    /*
        Clicking on a keyword node in the tree view to select it.
    */

    $('body').on('click','.ptm-keyword',function(){
        $('.ptm-keyword').removeClass('selected');
        $(this).addClass('selected');

        var type = $(this).attr('data-type');
        var id = $(this).attr('data-id');
        var dataSelector = '[data-type="' + type + '"]';
        if (id) {
            dataSelector += '[data-id="' + id + '"]';
        }

        var callerConfig = ActionCallerConfig[type];
        var caller = ActionCallerManager.GetCaller(type, id);

        if (caller) {
            SMDisplay.RefreshDetails(caller);
        }

        $('.ptm-result').hide();
        $('.ptm-result' + dataSelector).fadeIn();
    });

    /*
        General action button handling.
    */

    $('body').on('click', '.dnc-sm-action', function() {
        var $that = $(this);
        if ($that.hasClass('dnc-sm-running')) {
            return;
        }

        var callerType = $that.attr('data-caller-type');
        var callerId = $that.attr('data-caller-id');
        var parentId = $that.attr('data-caller-parent-id');
        var caller = null;
        if (callerType) {
            caller = ActionCallerManager.GetCaller(callerType, parentId ? parentId : callerId);
        }
        var actionId = $that.attr('data-action-id');
        var action = SiteManagerActions[actionId];
        var relatedActionsBlocked = false;
        var mainActionDetails = {
            action: action,
            caller: caller,
            logGroup: action.id + '.' + callerType + '.' + callerId
        };
        var doTreeScroll = true;

        var groupLabel = action.label;
        var topCaller = SiteManager.EnsureTopLevelCaller(caller);
        SMLog.RegisterGroup(mainActionDetails.logGroup, groupLabel);

        var callId = actionId + '.' + callerType + '.' + callerId;
        ActionLoaders[callId] = {
            loader: new AjaxLoader(actionId, callerType, callerId, action.icon),
            threads: []
        };

        function toggleActionButton(actionBlock, enabled) 
        {
            if (actionBlock[1] == '*') {
                if (enabled) {
                    $('.dnc-sm-action[data-action-id!="' + mainActionDetails.action.id + '"]')
                        .removeAttr('disabled')
                    ;
                } else {
                    $('.dnc-sm-action[data-action-id!="' + mainActionDetails.action.id + '"]')
                        .attr('disabled', 'disabled')
                    ;
                }

                return;
            }
            dataSelector = '[data-action-id="' + actionBlock[1] + '"]';

            if (actionBlock[2]) {
                dataSelector += '[data-caller-type="' + actionBlock[2] + '"]'
            }

            if (actionBlock[3]) {
                dataSelector += '[data-caller-id="' + actionBlock[3] + '"]';
            }

            var $button = $('body').find('.dnc-sm-action' + dataSelector);
            if (enabled) {
                $button.removeAttr('disabled');
            } else {
                $button.attr('disabled', 'disabled');
            }
        }

        function blockRelatedActions() 
        {
            if (! relatedActionsBlocked ) {

                // blocking "BlockedBy" buttons
                $.each(SiteManagerActions, function (actionId, action) {

                    var shouldBeBlocked = typeof action.blockedBy == 'object' && (
                            action.blockedBy.contains('*') ||
                            action.blockedBy.contains(mainActionDetails.action.id)
                        )
                    ;

                    if (mainActionDetails.action.id == actionId || !shouldBeBlocked) {
                        return;
                    }

                    var actionBlock;
                    if (! action.blockedBy.contains('*')) {
                        var tmpCaller = SiteManager.GetContextCaller(
                            mainActionDetails.caller, 
                            action.allowedCallerTypes
                        );
                        if (! tmpCaller) {
                            return;
                        }
                        actionBlock = [
                            mainActionDetails.action.id, 
                            actionId, 
                            tmpCaller.caller_type, 
                            tmpCaller.id
                        ];
                    } else {
                        actionBlock = [mainActionDetails.action.id, actionId]
                    }

                    BlockedActions[BlockedActions.length] = actionBlock;
                    toggleActionButton(actionBlock, false);
                });

                //blocking "blocks" => array() buttons
                if (mainActionDetails.action.blocks && mainActionDetails.action.blocks.length) {
                    for (var i = 0; i < mainActionDetails.action.blocks.length; i++) {

                        if (mainActionDetails.action.blocks[i] === '*') {

                            var tmpCallerType = mainActionDetails.caller 
                                ? mainActionDetails.caller.caller_type 
                                : ''
                            ;
                            var tmpCallerId = mainActionDetails.caller 
                                ? mainActionDetails.caller.id 
                                : ''
                            ;
                            var actionBlock = [
                                mainActionDetails.action.id, 
                                '*',
                                tmpCallerType, 
                                tmpCallerId
                            ];
                            BlockedActions[BlockedActions.length] = actionBlock;
                            toggleActionButton(actionBlock, false);
                            continue;
                        }

                        var tmpAction = SiteManagerActions[mainActionDetails.action.blocks[i]];
                        if (!tmpAction) {
                            continue;
                        }

                        var tmpCaller = SiteManager.GetContextCaller(
                            mainActionDetails.caller, 
                            tmpAction.allowedCallerTypes
                        );
                        if (! tmpCaller) {
                            continue;
                        }
                        
                        var actionBlock = [
                            mainActionDetails.action.id, 
                            mainActionDetails.action.blocks[i], 
                            tmpCaller.caller_type, 
                            tmpCaller.id
                        ];
                        BlockedActions[BlockedActions.length] = actionBlock;
                        toggleActionButton(actionBlock, false);
                    }
                }
                relatedActionsBlocked = true;
            }
        }

        function unblockRelatedActions() 
        {
            if (relatedActionsBlocked) {
                var newBlockedActions = [];
                var unblockedActions = [];
                var newBlockedActionIds = [];
                for (var i = 0; i < BlockedActions.length; i++) {
                    var blockedAction = BlockedActions[i];
                    if (blockedAction[0] != mainActionDetails.action.id) {
                        newBlockedActions[newBlockedActions.length] = blockedAction;
                        newBlockedActionIds[newBlockedActionIds.length] = blockedAction[1];
                    } else {
                        unblockedActions[unblockedActions.length] = blockedAction;
                    }
                }

                BlockedActions = newBlockedActions;

                for (var i = 0; i < unblockedActions.length; i++) {
                    if (! newBlockedActionIds.contains(unblockedActions[i])) {
                        toggleActionButton(unblockedActions[i], true);
                    }
                }

                relatedActionsBlocked = false;
            }
        }

        function startLoader() 
        {
            var groupId = callId;
            var newIndex = ActionLoaders[groupId].threads.length;
            ActionLoaders[groupId].threads[newIndex] = true;
            if (newIndex === 0) {
                ActionLoaders[groupId].loader.Show();
            } else {
                var allPreviousStopped = true;
                for (var i = 0; i < ActionLoaders[groupId].threads.length - 1; i++) {
                    if (ActionLoaders[groupId].threads[i] === true) {
                        allPreviousStopped = false;
                        break;
                    }
                }
                if (allPreviousStopped) {
                    ActionLoaders[groupId].loader.Show();
                }
            }
            blockRelatedActions();
        }

        function stopLoader() 
        {
            var groupId = callId;
            for (var i = 0; i < ActionLoaders[groupId].threads.length; i++) {
                if (ActionLoaders[groupId].threads[i] === false && i < ActionLoaders[groupId].threads.length - 1) {
                    continue;
                }

                ActionLoaders[groupId].threads[i] = false;
                if (i == ActionLoaders[groupId].threads.length - 1) {
                    ActionLoaders[groupId].loader.Hide();
                    unblockRelatedActions();
                }
                break;
            }
        }

        function indicateDetailsChange(original, modified) 
        {
            if (! original || ! modified) {
                return;
            }

            var callerConfig = ActionCallerConfig[original.caller_type];
            if (! callerConfig.details || ! callerConfig.details.length) {
                return;
            }

            var modProps = [];
            for (var i = 0; i < callerConfig.details.length; i++) {
                if (! callerConfig.details[i].property) {
                    continue;
                }

                var prop = callerConfig.details[i].property;
                if (
                    SiteManager.GetCallerProperty(
                        original, 
                        prop
                    ) != SiteManager.GetCallerProperty(
                        modified, 
                        prop
                    )
                ) {
                    modProps[modProps.length] = prop;
                }
            }

            for (var i = 0; i < modProps.length; i++) {
                var selector = '[data-caller-type="' + original.caller_type + '"]';
                if (original.id) {
                    selector += '[data-caller-id="' + original.id + '"]';
                }
                selector += '[data-caller-property="' + modProps[i] + '"]';

                setTimeout(function() {
                    $(selector)
                        .parents('.ptm-result__content__container')
                        .animate({scrollTop: 0}, 500)
                    ;
                    $(selector).parent().css('background', '#6f3');
                    $(selector).parent().animate({backgroundColor: '#fff'}, 5000, null, function() {
                        $(selector).parent().css('background', '');
                    });
                }, 100);
            }
        }

        function logActionResponse(actionId, response, group) 
        {
            var msg = 'Action ' + actionId + ' ';
            msg += response.signal.toUpperCase().replace(/[^\w]/, ' ');
            if (response.message) {
                msg += ': ' + response.message;
            } else {
                msg += '.';
            }

            console.log(' ');
            console.log('**********');
            console.log(msg);

            if (response.data && (response.data.length === undefined || response.data.length > 0)) {
                console.log('Data:');
                console.log(response.data);
            }
            if (response.callback_action_id) {
                console.log('Callback Action: ' + response.callback_action_id);
            }
            if (response.callback_action_caller) {
                console.log('Callback Action Caller:');
                console.log(response.callback_action_caller);
            }
            if (
                response.callback_action_data && 
                (
                    response.callback_action_data.length === undefined || 
                    response.callback_action_data.length > 0
                )
            ) {
                console.log('Callback Action Data:');
                console.log(response.callback_action_data);
            }

            console.log('**********');
            console.log(' ');

            if (response.message != '') {
                var msgGroup = group;
                var msgType = '';
                var msgContent = response.message;
                var msgTitle = '';
                var currentAction = SiteManagerActions[actionId];
                if (currentAction && currentAction.id != mainActionDetails.action.id) {
                    msgTitle = currentAction.label;
                }
                switch (response.signal) {
                    case 'success':
                        msgType = 'success';
                        break;
                    case 'warning':
                        msgType = 'warning';
                        break;
                    case 'failure':
                        msgType = 'danger';
                        break;
                    default:
                        msgType = 'info';
                }

                SMLog.AddMessage(msgGroup, msgType, msgTitle, msgContent);
            }
        }

        function doAction(
            action, 
            caller, 
            data, 
            threadGroupId, 
            threadId, 
            parentThreadGroupId, 
            parentThreadId
        ) {
            if (action.data) {
                if (! data) {
                    data = {};
                }
                $.each(action.data, function(dataVar, dataSource) {
                    if (typeof data[dataVar] !== 'undefined') {
                        return;
                    }
                    if (typeof dataSource === 'object') {
                        if (dataSource.function) {
                            var fn = dataSource.function;
                            data[dataVar] = window[fn](action, caller);
                        } else if (dataSource.value) {
                            data[dataVar] = dataSource.value;
                        } else if (dataSource.input_selector) {
                            var $sel = $(dataSource.input_selector);
                            data[dataVar] = $sel && $sel.size() > 0 ? $sel.val() : null;
                        } else if (dataSource.html_selector) {
                            var $sel = $(dataSource.html_selector);
                            data[dataVar] = $sel && $sel.size() > 0 ? $sel.html() : null;
                        } else if (dataSource.property) {
                            data[dataVar] = SiteManager.GetCallerProperty(
                                caller, 
                                dataSource.property
                            );
                        }
                    } else if (dataSource.indexOf("()") !== -1) {
                        var fn = dataSource.replace("()","");
                        data[dataVar] = window[fn](action, caller);
                    } else {
                        var $sel = $(dataSource);
                        data[dataVar] = $sel && $sel.size() > 0 ? $sel.val() : null;
                    }
                });
            }

            actionId = action.id;
            callerType = caller ? caller.caller_type : null;
            callerId = caller ? caller.id : null;

            var async = true;
            if (action.redirect === true) {
                async = false;
            }

            var threadsFired = false;
            var afterCallbacks = [];
            var rendererAjaxHandler = null;

            $.ajax({
                async: async,
                beforeSend: function(jqXHR, settings) {
                    startLoader();
                    console.log('Before:(' + actionId + ', ' + callerType + ', ' + callerId + ')');
                    console.log(ActionCallersRegistry);

                    if (threadGroupId) {
                        if (! ActionThreads[threadGroupId]) {
                            ActionThreads[threadGroupId] = [];
                        }
                        if (threadId >= 0) {
                            ActionThreads[threadGroupId][threadId] = true;
                        }
                    }
                },
                complete: function(jqXHR, textStatus) {
                    console.log('After:(' + actionId + ', ' + callerType + ', ' + callerId + ')');
                    console.log(ActionCallersRegistry);

                    if (! threadsFired && threadGroupId && threadId >= 0) {
                        ActionThreads[threadGroupId][threadId] = false;
                    }

                    if (threadGroupId && parentThreadGroupId && parentThreadId >= 0) {
                        var terminateParentThread = true;
                        if (ActionThreads[threadGroupId] && ActionThreads[threadGroupId].length) {
                            for (var i = 0; i < ActionThreads[threadGroupId].length; i++) {
                                if (ActionThreads[threadGroupId][i] === true) {
                                    terminateParentThread = false;
                                    break;
                                }
                            }
                        }

                        if (terminateParentThread) {
                            ActionThreads[parentThreadGroupId][parentThreadId] = false;
                        }
                    }

                    if (afterCallbacks.length > 0) {
                        for (var i = 0; i < afterCallbacks.length; i++) {
                            doActionAfter(afterCallbacks[i][0], afterCallbacks[i][1], afterCallbacks[i][2], afterCallbacks[i][3], i);
                        }
                        afterCallbacks = [];
                    }

                    if( ! rendererAjaxHandler) {
                        stopLoader();
                    } else {
                        rendererAjaxHandler.always(function() {
                            stopLoader();
                        });
                    }
                },
                data: {
                    action: 'dashnex-site-manager-call-action',
                    action_id: actionId,
                    caller_type: callerType,
                    caller_id: callerId,
                    data: data
                },
                dataType: 'json',
                error: function(jqXHR, textStatus, errorThrown){
                    console.log('Action ' + actionId + ' finished with an error.');
                    console.log(textStatus);
                    console.log(errorThrown);
                    console.log(jqXHR);
                    console.log(jqXHR.responseText);
                    var currentAction = SiteManagerActions[actionId];
                    SMLog.AddMessage(
                        mainActionDetails.logGroup, 
                        'danger', 
                        '', 
                        'Action <em>' 
                            + currentAction.label 
                            + '</em> finished with an error.<br/>Response text: ' 
                            + jqXHR.responseText
                    );
                },
                success: function(data, textStatus, jqXHR) {
                    if (! data || data.length == 0) {
                        console.log('Action ' + actionId + ' finished with unknown result.');
                        console.log(data);
                        console.log(textStatus);
                        console.log(jqXHR);
                        var currentAction = SiteManagerActions[actionId];
                        var msg = 'Action <em>' 
                            + currentAction.label 
                            + '</em> finished with unknown result.'
                        ;
                        if (jqXHR.responseText) {
                            msg += '<br/>Response text: ' + jqXHR.responseText;
                        }
                        SMLog.AddMessage(mainActionDetails.logGroup, 'danger', '', msg);

                        return;
                    }

                    var $clickAfter = null;
                    var threadGroup = actionId + '.' + callerType + '.' + callerId;
                    var threadIndex = 0;

                    $.each(data, function(i, response) {
                        logActionResponse(actionId, response, mainActionDetails.logGroup);
                        if (response.signal == 'failure') {
                            // TODO
                        } else if (response.signal == 'info') {
                            // TODO
                        } else if (response.signal == 'success') {
                            // TODO
                        } else if (response.signal == 'warning') {
                            // TODO
                        } else if (response.signal == 'refresh-tree') {
                            var refreshCaller = response.data ? response.data : caller;
                            SMDisplay.RefreshTreeNode(refreshCaller);
                        } else if (response.signal == 'refresh-details') {
                            var refreshCaller = response.data ? response.data : caller;
                            SMDisplay.RefreshDetails(refreshCaller);
                        } else if (response.signal == 'remove') {
                            var removeCaller = response.data ? response.data : caller;
                            var $parent = null;
                            if (removeCaller.caller_type == 'category-keyword') {
                                $parent = SMDisplay.$SelectTreeNode(
                                    ActionCallerManager.GetCaller('primary-keyword')
                                );
                            } else if (removeCaller.caller_type == 'content-keyword') {
                                $parent = SMDisplay
                                    .$SelectTreeNode(removeCaller)
                                    .parents('.ptm-categoryKeywordContainer')
                                    .find('.ptm-categoryKeyword')
                                ;
                            }
                            SMDisplay.RemoveNode(removeCaller);
                            ActionCallerManager.RemoveCaller(removeCaller.caller_type, caller.id);
                            if ($parent) {
                                $clickAfter = $parent;
                            }
                        } else if (response.signal == 'create') {
                            var createCaller = response.data;
                            var refId = null;
                            if (createCaller.caller_type == 'content-keyword') {
                                refId = createCaller.category_keyword_node_id;
                            }

                            ActionCallerManager.AddCaller(createCaller);
                            if(
                                [
                                    'primary-keyword', 
                                    'category-keyword', 
                                    'content-keyword'
                                ].contains(createCaller.caller_type)
                            ) {
                                rendererAjaxHandler = SMDisplay.RenderNode(createCaller, refId);
                                if (doTreeScroll) {
                                    rendererAjaxHandler.done(function() {
                                        setTimeout(
                                            function() {
                                                SMDisplay
                                                    .$SelectTreeNode(createCaller)
                                                    .parents('.ptm-sidebar__content')
                                                    .animate(
                                                        {
                                                            scrollTop: SMDisplay
                                                                .$SelectTreeNode(createCaller)
                                                                .position()
                                                                .top
                                                        }, 
                                                        500
                                                    )
                                                ;
                                            }, 
                                            100
                                        );
                                    });
                                    doTreeScroll = false;
                                }
                            }
                        } else if (response.signal == 'redirect') {
                            var url = response.data.url;
                            window.open(url, '_blank');
                        } else if (response.signal == 'refresh-data') {
                            var refreshCaller = response.data;
                            var callerConfig = ActionCallerConfig[refreshCaller.caller_type];
                            if (callerConfig.parent_type && callerConfig.parent_property) {
                                if (callerConfig.singleton) {
                                    var type = refreshCaller.caller_type;
                                    indicateDetailsChange(
                                        ActionCallersRegistry[type], 
                                        refreshCaller
                                    );
                                    ActionCallersRegistry[type] = refreshCaller;
                                } else {
                                    var type = refreshCaller.caller_type;
                                    var id = refreshCaller[callerConfig.parent_property].id;
                                    indicateDetailsChange(
                                        ActionCallersRegistry[type][id], 
                                        refreshCaller
                                    );
                                    ActionCallersRegistry[type][id] = refreshCaller;
                                }

                                var parentCaller = refreshCaller[callerConfig.parent_property];
                                if (parentCaller) {
                                    var parentConfig = ActionCallerConfig[parentCaller.caller_type];
                                    if (parentConfig.singleton) {
                                        var type = parentCaller.caller_type;
                                        indicateDetailsChange(
                                            ActionCallersRegistry[type], 
                                            parentCaller
                                        );
                                        ActionCallersRegistry[type] = parentCaller;
                                    } else {
                                        var type = parentCaller.caller_type;
                                        var id = parentCaller.id;
                                        indicateDetailsChange(
                                            ActionCallersRegistry[type][id], 
                                            parentCaller
                                        );
                                        ActionCallersRegistry[type][id] = parentCaller;
                                    }
                                }
                            } else {
                                if (callerConfig.singleton) {
                                    var type = refreshCaller.caller_type;
                                    indicateDetailsChange(
                                        ActionCallersRegistry[type], 
                                        refreshCaller
                                    );
                                    ActionCallersRegistry[type] = refreshCaller;
                                } else {
                                    var type = refreshCaller.caller_type;
                                    var id = refreshCaller.id;
                                    indicateDetailsChange(
                                        ActionCallersRegistry[type][id], 
                                        refreshCaller
                                    );
                                    ActionCallersRegistry[type][id] = refreshCaller;
                                }

                                $.each(ActionCallerConfig, function(type, config) {
                                    if (
                                        type == refreshCaller.caller_type ||
                                        config.parent_type != refreshCaller.caller_type ||
                                        ! config.parent_property
                                    ) {
                                        return;
                                    }

                                    if (config.singleton) {
                                        ActionCallersRegistry[type][config.parent_property] = 
                                            refreshCaller
                                        ;
                                    } else {
                                        var id = refreshCaller.id;
                                        if (
                                            ActionCallersRegistry[type] && 
                                            ActionCallersRegistry[type][id] && 
                                            ActionCallersRegistry[type][id][config.parent_property]
                                        ) {
                                            ActionCallersRegistry[type][id][config.parent_property] = refreshCaller;
                                        }
                                    }
                                });
                            }
                        } else if (response.signal == 'enable-indicator') {
                            var indicatorData = response.data;
                            var regId = indicatorData.caller_type + '.' + indicatorData.caller_id;
                            if (! CallerIndicators[regId]) {
                                CallerIndicators[regId] = [];
                            }
                            CallerIndicators[regId][CallerIndicators[regId].length] = indicatorData;
                            SMDisplay.EnableIndicator(indicatorData);
                        } else if (response.signal == 'disable-indicator') {
                            var indicatorData = response.data;
                            var regId = indicatorData.caller_type + '.' + indicatorData.caller_id;
                            if (CallerIndicators[regId] && CallerIndicators[regId].length) {
                                var newReg = [];
                                for (var j = 0; j < CallerIndicators[regId].length; j++) {
                                    if (CallerIndicators[regId][j].indicator_id == indicatorData.indicator_id) {
                                        continue;
                                    }
                                    newReg[newReg.length] = CallerIndicators[regId][j];
                                }
                                CallerIndicators[regId] = newReg;
                            }
                            SMDisplay.DisableIndicator(indicatorData);
                        }

                        if (response.callback_action_id) {
                            var callbackCaller = response.callback_action_caller;

                            var callbackAction = SiteManagerActions[response.callback_action_id];

                            if (callbackCaller && callbackAction) {
                                if (response.signal != 'after-callback') {
                                    if (threadGroupId != '' && threadId >= 0) {
                                        doAction(
                                            callbackAction, 
                                            callbackCaller, 
                                            response.callback_action_data, 
                                            threadGroup, 
                                            threadIndex++, 
                                            threadGroupId, 
                                            threadId
                                        );
                                    } else {
                                        doAction(
                                            callbackAction, 
                                            callbackCaller, 
                                            response.callback_action_data, 
                                            threadGroup, 
                                            threadIndex++
                                        );
                                    }
                                } else {
                                    afterCallbacks[afterCallbacks.length] = [
                                        threadGroup, 
                                        callbackAction, 
                                        callbackCaller, 
                                        response.callback_action_data
                                    ];
                                }
                                threadsFired = true;
                            }
                        }
                    });

                    if ($clickAfter && $clickAfter.size() > 0) {
                        $clickAfter.click();
                    }
                },
                type: 'POST',
                url: ajaxurl
            });
        }

        function doActionAfter(threadGroupId, action, caller, data, threadId) 
        {
            var doIt = true;
            if (ActionThreads[threadGroupId] && ActionThreads[threadGroupId].length) {
                for (var i = 0; i < ActionThreads[threadGroupId].length; i++) {
                    if (ActionThreads[threadGroupId][i] === true) {
                        doIt = false;
                        break;
                    }
                }
            }

            if (doIt) {
                doAction(action, caller, data, threadGroupId, threadId);
            } else {
                setTimeout(function() {
                    doActionAfter(threadGroupId, action, caller, data, threadId);
                }, 500);
            }
        }

        if (action.modal && action.modal.selector) {
            var $modal = $(action.modal.selector);

            if (action.modal.data) {
                $.each(action.modal.data, function(dataSelector, dataConfig) {
                    var $field = $(dataSelector);
                    var val = '';

                    if (dataConfig[0].match(/^data-/)) {
                        val = $that.attr(dataConfig[0]);
                    } else if (dataConfig[0] != '') {
                        val = caller[dataConfig[0]];
                    } else {
                        val = '';
                    }

                    if (dataConfig[1] == 'val') {
                        $field.val(val);
                    } else if (dataConfig[1] == 'html') {
                        $field.html(val);
                    }
                });
            }

            if (! action.customHandler && action.modal.submitSelector) {
                var $submit = $(action.modal.submitSelector);
                var submitClicked = false;
                $submit.unbind('click').on('click', function() {
                    submitClicked = true;
                    doAction(action, caller, null);
                });
                $modal.on('submit', 'form', function(e) {
                    e.preventDefault();
                    if (! submitClicked) {
                        $submit.click();
                    }
                });
            }

            $modal.modal('show');
            $modal.on('submit', 'form', function(e) {
                e.preventDefault();
                return false;
            });
        } else if (! action.customHandler) {
            doAction(action, caller, null);
        }
    });

    $('.ptm-primaryKeyword').click();
    SMLog.Render();

    $('.modal').on('shown.bs.modal', function() {
        $(this).find('input').focus();
    });
});