/**
 * force load entry content with iframe when view entry
 *
 * @access public
 * @return void
 */
(function()
{
    var redirect = function()
    {
        if(!config) return;
        if(config.currentModule == 'index')
        {
            if(config.currentMethod == 'index' && window.frameElement && window.frameElement.tagName == 'IFRAME') window.top.location.href = location.href;
        }
        else if((!window.frameElement || window.frameElement.tagName != 'IFRAME') && typeof v != 'undefined' && typeof v.entryID != 'undefined' && v.entryID != '')
        {
            location.href = config.webRoot + 'sys/index.php?entryID=' + v.entryID + '&entryUrl=' + encodeURIComponent(window.location.pathname + window.location.search);
        }
    };

    if(config.defaultView != 'xhtml')
    {
        redirect();
        $(redirect);
    }
}());

$.extend(
{
    setAjaxForm: function(formID, callback, beforeSubmit)
    {
        if($(document).data('setAjaxForm:' + formID)) return;

        form = $(formID);

        var options =
        {
            target  : null,
            timeout : config.timeout,
            dataType:'json',

            success: function(response)
            {
                var submitButton = $(formID).find(':input[type=submit], .submit');

                /* The response is not an object, some error occers, bootbox.alert it. */
                if($.type(response) != 'object')
                {
                    $.enableForm(formID);
                    if(response) return bootbox.alert(response);
                    return bootbox.alert('No response.');
                }

                /* The response.result is success. */
                if(response.result == 'success')
                {
                    if(response.message && response.message.length)
                    {
                        submitButton.popover($.extend(
                        {
                            trigger: 'manual',
                            content: response.message,
                            tipClass: 'popover-success popover-form-result',
                            placement: response.placement ? response.placement : 'right'
                        }, submitButton.data())).popover('show');
                        setTimeout(function(){submitButton.popover('destroy')}, 2000);
                    }

                    if($.isFunction(callback)) return callback(response);

                    if($('#responser').length && response.message && response.message.length)
                    {
                        $('#responser').html(response.message).addClass('red f-12px').show().delay(3000).fadeOut(100);
                    }

                    if(response.closeModal)
                    {
                        setTimeout($.zui.closeModal, 1200);
                    }

                    if(response.callback)
                    {
                        var rcall = window[response.callback];
                        if($.isFunction(rcall))
                        {
                            if(rcall() === false)
                            {
                                return;
                            }
                        }
                    }

                    if(response.locate)
                    {
                        if(response.locate == 'loadInModal')
                        {
                            var modal = $('.modal');
                            setTimeout(function()
                            {
                                modal.load(modal.attr('ref'), function(){$(this).find('.modal-dialog').css('width', $(this).data('width'));
                                $.zui.ajustModalPosition()})
                            }, 1000);
                        }
                        else
                        {
                            var reloadUrl = response.locate == 'reload' ? location.href : response.locate;
                            setTimeout(function(){location.href = reloadUrl;}, 1200);
                        }
                    }

                    if(response.ajaxReload)
                    {
                        var $target = $(response.ajaxReload);
                        if($target.length === 1)
                        {
                            $target.load(document.location.href + ' ' + response.ajaxReload, function()
                            {
                                // $target.dataTable();
                                $target.find('[data-toggle="modal"]').modalTrigger();
                            });
                        }
                    }

                    return true;
                }

                /**
                 * The response.result is fail.
                 */

                $.enableForm(formID);
                /* The result.message is just a string. */
                if($.type(response.message) == 'string')
                {
                    if($('#responser').length == 0)
                    {
                        submitButton.popover($.extend(
                        {
                            trigger: 'manual',
                            content: response.message,
                            tipClass: 'popover-danger popover-form-result',
                            placement: response.placement ? response.placement : 'right'
                        }, submitButton.data())).popover('show');
                        setTimeout(function(){submitButton.popover('destroy')}, 2000);
                    }
                    $('#responser').html(response.message).addClass('red small text-danger').show().delay(5000).fadeOut(100);
                }

                /* The result.message is just a object. */
                if($.type(response.message) == 'object')
                {
                    $.each(response.message, function(key, value)
                    {
                        /* Define the id of the error objecjt and it's label. */
                        var errorOBJ   = '#' + key;
                        var errorLabel = key + 'Label';

                        /* Create the error message. */
                        var errorMSG = '<span id="' + errorLabel + '" for="' + key  + '"  class="text-error red">';
                        if($.type(value) == 'string')
                        {
                            errorMSG += value;
                        }
                        else
                        {
                            $.each(value, function(subKey, subValue)
                            {
                                errorMSG += subKey != value.length - 1 ? subValue.replace(/[\。|\.]/, ';') : subValue;
                            })
                        }
                        errorMSG += '</span>';

                        /* Append error message, set style and set the focus events. */
                        $('#' + errorLabel).remove();
                        var $errorOBJ = $(formID).find(errorOBJ);
                        if($errorOBJ.closest('.input-group').length > 0)
                        {
                            $errorOBJ.closest('.input-group').after(errorMSG)
                        }
                        else
                        {
                            $errorOBJ.parent().append(errorMSG);
                        }
                        $errorOBJ.css('margin-bottom', 0);
                        $errorOBJ.css('border-color','#953B39')
                        $errorOBJ.change(function()
                        {
                            $errorOBJ.css('margin-bottom', 0);
                            $errorOBJ.css('border-color','')
                            $('#' + errorLabel).remove();
                        });
                    })

                    /* Focus the first error field thus to nitify the user. */
                    var firstErrorField = $('#' +$('span.red').first().attr('for'));
                    var topOffset;
                    if(firstErrorField.length) topOffset = parseInt(firstErrorField.offset().top) - 20;   // 20px offset more for margin.

                    /* If there's the navbar-fixed-top element, minus it's height. */
                    if($('.navbar-fixed-top').size())
                    {
                        topOffset = topOffset - parseInt($('.navbar-fixed-top').height());
                    }

                    /* Scroll to the error field and foucus it. */
                    $(document).scrollTop(topOffset);
                    firstErrorField.focus();
                }

                if($.isFunction(callback)) return callback(response);
            },

            /* When error occers, alert the response text, status and error. */
            error: function(jqXHR, textStatus, errorThrown)
            {
                $.enableForm(formID);
                if(textStatus == 'timeout')
                {
                    bootbox.alert(v.lang.timeout);
                    return false;
                }
                bootbox.alert(jqXHR.responseText + textStatus + errorThrown);
            }
        };

        /* Call ajaxSubmit to sumit the form. */
        $(document).on('submit', formID, function()
        {
            $.disableForm(formID);
            if(!beforeSubmit || beforeSubmit() !== false)
            {
                $(this).ajaxSubmit(options);
            }
            else
            {
                $.enableForm(formID);
            }
            return false;    // Prevent the submitting event of the browser.
        }).data('setAjaxForm:' + formID, true);
    },

    /* Switch the label and disabled attribute for the submit button in a form. */
    setSubmitButton: function(formID, action)
    {
        var submitButton = $(formID).find(':submit');

        label    = submitButton.val();
        loading  = submitButton.data('loading');
        disabled = action == 'disable';

        submitButton.attr('disabled', disabled);
        submitButton.val(loading);
        submitButton.data('loading', label);
    },

    /* Disable a form. */
    disableForm: function(formID)
    {
        $.setSubmitButton(formID, 'disable');
    },

    /* Enable a form. */
    enableForm: function(formID)
    {
        $.setSubmitButton(formID, 'enable');
    }
});

$.extend(
{
    /**
     * Set ajax loader.
     *
     * Bind click event for some elements thus when click them,
     * use $.load to load page into target.
     *
     * @param string selector
     * @param string target
     */
    setAjaxLoader: function(selector, target)
    {
        /* Avoid duplication of binding */
        var data = $('body').data('ajaxLoader');
        if(data && data[selector]) return;
        if(!data) data = {};
        data[selector] = true;
        $('body').data('ajaxLoader', data);

        $(document).on('click', selector, function()
        {
            var url = $(this).attr('href');
            if(!url) url = $(this).data('rel');
            if(!url) return false;

            var $target = $(target);
            if(!$target.size()) return false;

            var width = $(this).data('width');
            $target.load(url, function()
            {
                if(width) $target.find('.modal-dialog').css('width', width);
                if($target.hasClass('modal') && $.zui.ajustModalPosition)
                {
                    $.zui.ajustModalPosition();
                    $target.find('.modal-body').on('resize', function()
                    {
                        $.zui.ajustModalPosition();
                    });
                }

                $.zui.initPage($target);
            });

            return false;
        });
    },

    /**
     * Set ajax jsoner.
     *
     * @param string   selector
     * @param object   callback
     */
    setAjaxJSONER: function(selector, callback)
    {
        $(document).on('click', selector, function()
        {
            /* Try to get the href of current element, then try it's data-rel attribute. */
            url = $(this).attr('href');
            if(!url) url = $(this).data('rel');
            if(!url) return false;

            $.getJSON(url, function(response)
            {
                /* If set callback, call it. */
                if($.isFunction(callback)) return callback(response);

                /* If the response has message attribute, show it in #responser or alert it. */
                if(response.message)
                {
                    if($('#responser').length)
                    {
                        $('#responser').html(response.message);
                        $('#responser').addClass('text-info f-12px');
                        $('#responser').show().delay(3000).fadeOut(100);
                    }
                    else
                    {
                        bootbox.alert(response.message);
                    }
                }

                /* If the response has locate param, locate the browse. */
                if(response.locate) return location.href = response.locate;

                /* If target and source returned in reponse, update target with the source. */
                if(response.target && response.source)
                {
                    $(response.target).load(response.source);
                }
            });

            return false;
        });
    },

    /**
     * Set ajax deleter.
     *
     * @param  string $selector
     * @access public
     * @return void
     */
    setAjaxDeleter: function (selector, callback)
    {
        var bindMap = $(document).data('ajaxDeleterBindMap') || {};
        if(bindMap[selector]) return;

        $(document).on('click', selector, function()
        {
            if($(this).parents('.dropdown.open').length) $(this).parents('.dropdown').removeClass('open');

            if(confirm(v.lang.confirmDelete))
            {
                var deleter = $(this);
                deleter.text(v.lang.deleteing);

                $.getJSON(deleter.attr('href'), function(data)
                {
                    if ((callback && callback(data)) === false) {
                        return;
                    }
                    if(data.result == 'success')
                    {
                        if($(selector).hasClass('reloadModal')) return $.reloadAjaxModal(1200, deleter.parents('.modal-dialog').width());
                        if(data.locate) return location.href = data.locate;
                        return location.reload();
                    }
                    else
                    {
                        alert(data.message);
                        return location.reload();
                    }
                });
            }
            return false;
        });

        bindMap[selector] = true;
        $(document).data('ajaxDeleterBindMap', bindMap)
    },

    /**
     * Set reload deleter.
     *
     * @param  string $selector
     * @access public
     * @return void
     */
    setReloadDeleter: function (selector)
    {
        $(document).on('click', selector, function()
        {
            if(confirm(v.lang.confirmDelete))
            {
                var deleter = $(this);
                deleter.text(v.lang.deleteing);

                $.getJSON(deleter.attr('href'), function(data)
                {
                    var afterDelete = deleter.data('afterDelete');
                    if($.isFunction(afterDelete))
                    {
                        $.proxy(afterDelete, deleter)(data);
                    }

                    if(data.result == 'success')
                    {
                        var table     = $(deleter).closest('table');
                        var replaceID = table.attr('id');

                        table.wrap("<div id='tmpDiv'></div>");
                        var $tmpDiv = $('#tmpDiv');
                        $tmpDiv.load(document.location.href + ' #' + replaceID, function()
                        {
                            $tmpDiv.replaceWith($tmpDiv.html());
                            var $target = $('#' + replaceID);
                            $target.find('.reloadDeleter').data('afterDelete', afterDelete);
                            $target.find('[data-toggle="modal"]').modalTrigger();
                            if($target.hasClass('table-data'))
                            {
                                // $target.dataTable();
                            }
                            if(typeof sortTable == 'function')
                            {
                                sortTable();
                            }
                            else
                            {
                                $('tfoot td').css('background', 'white').unbind('click').unbind('hover');
                            }
                        });
                    }
                    else
                    {
                        alert(data.message);
                    }
                });
            }
            return false;
        });
    },

    /**
     * Set reload.
     *
     * @param  string $selector
     * @access public
     * @return void
     */
    setReload: function (selector)
    {
        $(document).on('click', selector, function()
        {
            var reload = $(this);
            $.getJSON(reload.attr('href'), function(data)
            {
                if(data.result == 'success')
                {
                    var table     = $(reload).closest('table');
                    var replaceID = table.attr('id');

                    table.wrap("<div id='tmpDiv'></div>");
                    $('#tmpDiv').load(document.location.href + ' #' + replaceID, function()
                    {
                        $('#tmpDiv').replaceWith($('#tmpDiv').html());
                        if(typeof sortTable == 'function')
                        {
                            sortTable();
                        }
                        else
                        {
                            $('tfoot td').css('background', 'white').unbind('click').unbind('hover');
                        }
                    });
                }
                else
                {
                    alert(data.message);
                }
            });
            return false;
        });
    },

    /**
     * Reload ajax modal.
     *
     * @param int duration
     * @access public
     * @return void
     */
    reloadAjaxModal: function(duration, width)
    {
        if(typeof(duration) == 'undefined') duration = 1000;
        setTimeout(function()
        {
            var modal = $('#ajaxModal');
            modal.load(modal.attr('ref'), function()
            {
                if(typeof(width) == 'undefined') width = $(this).data(width);
                $(this).find('.modal-dialog').css('width', width);
                $.zui.ajustModalPosition()
            })
        }, duration);
    }
});

/**
 * Judge the string is a integer number
 *
 * @access public
 * @return bool
 */
function isNum(s)
{
    if(s!=null)
    {
        var r, re;
        re = /\d*/i;
        r = s.match(re);
        return (r == s) ? true : false;
    }
    return false;
}

/**
 * Create link.
 *
 * @param  string $moduleName
 * @param  string $methodName
 * @param  string $vars
 * @param  string $viewType
 * @access public
 * @return string
 */
function createLink(moduleName, methodName, vars, viewType)
{
    if(!viewType) viewType = config.defaultView;
    if(vars)
    {
        vars = vars.split('&');
        for(i = 0; i < vars.length; i ++) vars[i] = vars[i].split('=');
    }

    appName = config.appName;
    router  = config.router;

    if(moduleName.indexOf('.') >= 0)
    {
        moduleNames = moduleName.split('.');
        appName     = moduleNames[0];
        moduleName  = moduleNames[1];
        router      = router.replace(config.appName, appName);
    }

    if(config.requestType == 'PATH_INFO')
    {
        link = config.webRoot + appName + '/' + moduleName + config.requestFix + methodName;
        if(vars)
        {
            if(config.pathType == "full")
            {
                for(i = 0; i < vars.length; i ++) link += config.requestFix + vars[i][0] + config.requestFix + vars[i][1];
            }
            else
            {
                for(i = 0; i < vars.length; i ++) link += config.requestFix + vars[i][1];
            }
        }
        link += '.' + viewType;
    }
    else
    {
        link = router + '?' + config.moduleVar + '=' + moduleName + '&' + config.methodVar + '=' + methodName + '&' + config.viewVar + '=' + viewType;
        if(vars) for(i = 0; i < vars.length; i ++) link += '&' + vars[i][0] + '=' + vars[i][1];
    }
    return link;
}

/**
 * Set required fields, add star class to them.
 *
 * @access public
 * @return void
 */
function setRequiredFields()
{
    if(!config.requiredFields) return false;
    requiredFields = config.requiredFields.split(',');
    for(i = 0; i < requiredFields.length; i++)
    {
        $('#' + requiredFields[i]).closest('td,th').prepend("<div class='required required-wrapper'></div>");
        var colEle = $('#' + requiredFields[i]).closest('[class*="col-"]');
        if(colEle.parent().hasClass('form-group')) colEle.addClass('required');
    }
}

/**
 * Select lang.
 *
 * @param  string $lang
 * @access public
 * @return void
 */
function selectLang(lang)
{
    $.cookie('lang', lang, {expires:config.cookieLife, path:config.webRoot});
    location.href = removeAnchor(location.href);
}

/**
 * Set theme.
 *
 * @param  string theme
 * @access public
 * @return void
 */
function selectTheme(theme)
{
    $.cookie('theme', theme, {expires:config.cookieLife, path:config.webRoot});
    location.href = removeAnchor(location.href);
}

/**
 * Remove anchor from the url.
 *
 * @param  string $url
 * @access public
 * @return string
 */
function removeAnchor(url)
{
    pos = url.indexOf('#');
    if(pos > 0) return url.substring(0, pos);
    return url;
}

/**
 * Ping to keep login
 *
 * @access public
 * @return void
 */
function ping()
{
    /* get showed notice ids. */
    var notice = getShowedNotice().join(',');

    $.get(createLink('misc', 'ping', 'notice=' + notice), function(response)
    {
        if(typeof(response.notices) != 'undefined')
        {
            for(key in response.notices)
            {
                showNotice(response.notices[key]);
            }
        }
    }, 'json');
}

/**
 * get showed notice id.
 *
 * @access public
 * @return array
 */
function getShowedNotice()
{
    var ids = [];
    $('.messager-notification[data-id]').each(function()
    {
        ids.push($(this).data('id'));
    });
    return ids;
}

/**
 * Show a notice.
 *
 * @param  object $notice
 * @access public
 * @return void
 */
function showNotice(notice)
{
    if (notice.app && $.getEntry)
    {
        var entry = $.getEntry(notice.app);
        if (entry)
        {
            var title = entry.name;
            if(notice.title)
            {
                if(notice.title !== title) title += ' - <small>' + notice.title + '</small>';
            }
            $.extend(notice,
            {
                title: title,
            });
        }
    }
    var msg = $.showAppNotification($.extend(
    {
        html: true,
        onHide: function()
        {
            if(this.notice && this.notice.read) $.get(this.notice.read);
        }
    }, notice));
    msg.notice = notice;
    msg.$.attr(
    {
        'data-id': notice.id,
        'data-read': notice.read,
    }).on('click', '.messager-content:not(:has(a[data-toggle=modal]))', function()
    {
        var $a = $(this).find('a');
        var appID = $a.data('id') || $a.data('appid');
        if(appID) $.openEntry(appID, $a.attr('href'));
        msg.hide();
        return false;
    }).on('mouseup', '.messager-content a[data-toggle=modal]', function()
    {
        msg.hide();
        return false;
    });
    return msg;
}

/**
 * Make form condensed
 *
 * @access public
 * @return void
 */
function condensedForm()
{
    $('.form-condensed legend').click(function()
    {
        $(this).closest('fieldset').toggleClass('collapsed');
    });
}

/**
 * Set page actions
 *
 * @access public
 * @return void
 */
function setPageActions()
{
    var bar = $('.page-actions'), barTop, barWidth, timeoutFn;
    if(bar.length)
    {
        barTop = bar.offset().top + bar.outerHeight();
        barWidth = bar.width();
        wW = 0;
        $(window).scroll(fixPageActions).resize(function()
        {
            var winW = $(window).width();
            if(Math.abs(wW - winW) < 100) return;
            wW = winW;
            bar = $('.page-actions');
            bar.removeClass('fixed');
            bar.css('width', '100%');
            barTop = bar.offset().top + bar.outerHeight();
            barWidth = bar.width();
            fixPageActions();
        });
        fixPageActions();
    }

    function fixPageActions()
    {
        if(timeoutFn)
        {
            clearTimeout(timeoutFn);
            timeoutFn = null;
        }
        timeoutFn = setTimeout(function()
        {
            var $win = $(window);
            var wH = $win.height();
            var fixed = barTop > wH && $win.scrollTop() < (barTop - wH);
            if(fixed)
            {
                bar.css('width', barWidth);
            }
            $('body').toggleClass('page-actions-fixed', fixed);
            bar.toggleClass('fixed', fixed);
        }, 50);
    }
}

/**
 * Show drop menu.
 *
 * @param  string $objectType product|project
 * @param  int    $objectID
 * @param  string $module
 * @param  string $method
 * @param  string $extra
 * @access public
 * @return void
 */
function showDropMenu(objectType, objectID, module, method, extra)
{
    var li = $('#currentItem').closest('li');
    if(li.hasClass('show')) {li.removeClass('show'); return;}

    if(!li.data('showagain'))
    {
        li.data('showagain', true);
        $(document).click(function() {li.removeClass('show');});
        $('#dropMenu, #currentItem').click(function(e){e.stopPropagation();});
    }
    $.get(createLink(objectType, 'ajaxGetDropMenu', "objectID=" + objectID + "&module=" + module + "&method=" + method + "&extra=" + extra), function(data){ $('#dropMenu').html(data).find('#search').focus();});

    li.addClass('show');
}

/**
 * Search items.
 *
 * @param  string $keywords
 * @param  string $objectType
 * @param  int    $objectID
 * @param  string $module
 * @param  string $method
 * @param  string $extra
 * @access public
 * @return void
 */
function searchItems(keywords, objectType, objectID, module, method, extra)
{
    if(keywords == '')
    {
        showMenu = 0;
        showDropResult(objectType, objectID, module, method, extra);
    }
    else
    {
        keywords = encodeURI(keywords);
        if(keywords != '-') $.get(createLink(objectType, 'ajaxGetMatchedItems', "keywords=" + keywords + "&module=" + module + "&method=" + method + "&extra=" + extra), function(data){$('#searchResult').html(data);});
    }
}

/**
 * Show or hide more items.
 *
 * @access public
 * @return void
 */
function switchFinished()
{
    $('#search').width($('#search').width()).focus();
    $('#finishedMenu').width($('#defaultMenu').outerWidth());
    $('#searchResult').removeClass('show-suspend');
    $('#searchResult').toggleClass('show-finished');
}

/**
 * Show or hide more items.
 *
 * @access public
 * @return void
 */
function switchSuspend()
{
    $('#search').width($('#search').width()).focus();
    $('#suspendMenu').width($('#defaultMenu').outerWidth());
    $('#searchResult').removeClass('show-finished');
    $('#searchResult').toggleClass('show-suspend');
}

/**
 * Set form action and submit.
 *
 * @param  url    $actionLink
 * @param  string $hiddenwin 'hiddenwin'
 * @access public
 * @return void
 */
function setFormAction(actionLink, hiddenwin, obj)
{
    $form = typeof(obj) == 'undefined' ? $('form') : $(obj).closest('form');
    if(hiddenwin) $form.attr('target', hiddenwin);
    else $form.removeAttr('target');

    $form.attr('action', actionLink).submit();
}

/**
 * Fix menus of navbar.
 *
 * @access public
 * @return void
 */
function fixNavbar()
{
    if($('.navbar-nav').length == 0) return false;

    var $navbar     = $('.navbar-nav');
    var navWidth    = $('#mainNavbar').width();
    var headerWidth = $('.navbar-header').width();
    var menuWidth   = $navbar.width();
    var rightWidth  = $('.dashboard-actions').length == 0 ? 100 : 200;

    if(menuWidth > navWidth - headerWidth - rightWidth)
    {
        $navbar.find('.moreMenu').removeClass('hidden');
        var lastNav = $('.navbar-nav > li').not('.moreMenu').last();
        $navbar.find('.moreMenu .dropdown-menu').prepend(lastNav);

        fixNavbar();
    }
}
