
var objFilesFmErrorHandler = new FilesFmErrorHandler ();

function FilesFmErrorHandler ()
{

    var strLogToken = 'd2881e1e5226c74f41a0132cb186fb35';
    var strLogUrl = 'https://ua.files.fm/post_log?token=' + strLogToken;
    
    intStackNum = 0;
    
    
    function init()
    {
        // Register global error handling function
        window.onerror = function (message_in, filename_in, linenum_in)
        {
            // Just coution to avoid inifnite loops
            if (intStackNum > 1)
                return false;

            var message = reduce(message_in, 2);
            var filename = reduce(filename_in);
            var linenum = reduce(linenum_in);

            intStackNum++;

            var objError = {
                                'message': message,
                                'url': filename,
                                'line': linenum,
                                'col': null,
                                'name': null,
                                'stack': null
                           };
                       
            if (arguments.length > 3)
            {
                objError['col'] = reduce(arguments[3]);
            }
            if (arguments.length > 4)
            {
                if (arguments[4] != null && typeof arguments[4]['name'] != 'undefined')
                {
                    objError['name'] = reduce(arguments[4]['name']);
                }
                if (arguments[4] != null && typeof arguments[4]['stack'] != 'undefined')
                {
                    objError['stack'] = reduce(arguments[4]['stack']);
                }
            }
            
            sendLogEntry ({'Type': 'JS-Runtime-Error', 'Data': objError});
        
            intStackNum--;
            return true; 
        }
        
        $(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {
            
            if ( console )
            {
                console.error('XHR canceled!');
            }
            
            if ( typeof( jqXHR.skipLogOnCancel ) != 'undefined' && jqXHR.skipLogOnCancel === true )
            {
                if ( console )
                {
                    console.log('Skip error log!');
                }
                
                return;
            }
            
            var objXHR = null;
            if (typeof(jqXHR) != 'undefined')
                objXHR = reduce(jqXHR);

            var objAjaxSettings = null;
            if (typeof(ajaxSettings) != 'undefined')
                objAjaxSettings = reduce(ajaxSettings);

            var objThrownError = null;
            if (typeof(thrownError) != 'undefined')
                objThrownError = reduce(thrownError);

            objError = {
                'XHR': objXHR, 
                'AjaxSettings': objAjaxSettings, 
                'ThrownError': objThrownError
            };
            // sendLogEntry ({'Type': 'Ajax-Error', 'Data': objError});
        });
        
    }
    
    var strSendMessageTextWithNextJSError = null;
    
    this.sendLogEntry=sendLogEntry;
    function sendLogEntry (objLog)
    {
        // Collect info about navigator, limit to scalar values
        var objNavigator = null;
        if (typeof(navigator) != 'undefined')
            objNavigator = reduce(navigator);
        
        // Collect info about global scalar variables.
        //var objGlobalVars = reduce(window);
           
        if ( typeof(strSendMessageTextWithNextJSError) != 'undefined' && strSendMessageTextWithNextJSError != null )
        {
            objLog['Data'].included_message = strSendMessageTextWithNextJSError;
            strSendMessageTextWithNextJSError = null;
        }
        
        var strURL = window.location.href;
        // Prepare strings from objects, allso run decycle to avoid infinite loop if cyclic object found.
        var strLogJSON = JSON.stringify(JSON.decycle(objLog['Data']));
        var strNavigatorJSON = JSON.stringify(JSON.decycle(objNavigator));
        //var strGlobalVarsJSON = JSON.stringify(JSON.decycle(objGlobalVars));

        // We use http form to subit data to server over https. Can not use ajax because of http->https restrictions in older browsers.
        if ($('#error_logging_form').size()==0)
        {
            $('body').append('<div style="width: 1px; height: 1px; overflow: hidden;"><iframe id="error_logging_form_iframe" name="error_logging_form_iframe"></iframe><form target="error_logging_form_iframe" id="error_logging_form" method="post" action="'+strLogUrl+'"><input type="hidden" name="Log" id="error_logging_form_log_field" /><input type="hidden" name="Navigator" id="error_logging_form_navigator_field" /><input type="hidden" name="Vars" id="error_logging_form_vars_field" /><input type="hidden" name="Type" id="error_logging_form_type_field" /><input type="hidden" name="Url" id="error_logging_form_url_field" /><input type="submit" value="submit" /></form></div>');
        }

        // Set input values
        $('#error_logging_form_url_field').val(strURL);
        $('#error_logging_form_type_field').val(objLog['Type']);
        $('#error_logging_form_log_field').val(strLogJSON);
        $('#error_logging_form_navigator_field').val(strNavigatorJSON);
        //$('#error_logging_form_vars_field').val(strGlobalVarsJSON);
        $('#error_logging_form').submit();
    }
    
    
    this.reduce=reduce;
    function reduce (mix, intMaxLevel, intCurrentLevel)
    {
        if (typeof mix == 'undefined' || mix == null)
            return null;
            
        if (typeof(intMaxLevel) == 'undefined' || intMaxLevel === null)
            intMaxLevel = 1;
        if (typeof(intCurrentLevel) == 'undefined' || intCurrentLevel === null)
            intCurrentLevel = 0;
        
        var ret = mix;
        if (!(/boolean|number|string/).test(typeof mix))
        {
            ret = {};
            for(var key in mix)
            {
                if ((/boolean|number|string/).test(typeof mix[key]))
                    ret[key] = mix[key];
                else if (intMaxLevel > intCurrentLevel+1)
                    ret[key] = reduce (mix[key], intMaxLevel, intCurrentLevel+1);
            }
        }
        return ret;
    }
    
    
    // !! Run initalization
    init();
    
}