

function isHidden() {
    let hidden = false;
    try {
        hidden = document.hidden;
    } catch(err) { hidden = false;}
    return hidden;
}

    function do_data_load(callback_data) {
        let ans_id = callback_data.hasOwnProperty('answer_id') ? callback_data.answer_id : 'answer';
        let should_stop = callback_data.hasOwnProperty('should_stop') ? callback_data.should_stop() : false;
        if (should_stop) {
            console.log('updating ' + ans_id +' stopped');
            return;
        }
        let need_pause = callback_data.hasOwnProperty('need_pause') ? callback_data.need_pause() : isHidden();
        if (need_pause) {
            setTimeout(do_data_load, 5000, callback_data);
            do_set_answer(statuses.hidden, 'window not visible, update paused', ans_id);
            return;
        }
        let ans_leg = callback_data.hasOwnProperty('hr_legend') ? callback_data.hr_legend : 'info';
        do_set_answer(statuses.loading, 'reloading ' + ans_leg + '...', ans_id);
        let xmlhttp = getXmlHttp();
        let url = callback_data.hasOwnProperty('url') ? callback_data.url : callback_data.get_url();
        if (callback_data.hasOwnProperty('post_data')) {
            xmlhttp.open('POST', url);
        } else {
            xmlhttp.open('GET', url);
        }
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState === 4) {
                if (xmlhttp.status === 200) {
                    try {
                        let res = JSON.parse(xmlhttp.responseText);
                        document.getElementById('raw_data').innerHTML = xmlhttp.responseText;
                        if (res['success']) {
                            callback_data.on_load(res);
                            do_set_answer(statuses.ok, ans_leg + ' updated', ans_id);
                            if (callback_data.hasOwnProperty('do_once') && callback_data.do_once) {
                                return;
                            }
                        } else {
                            do_set_answer(statuses.error, ans_leg + ' with error: ' + xmlhttp.responseText, ans_id);
                        }
                    } catch(err) {
                        do_set_answer(statuses.error, 'error on ' + ans_leg + ' parse: ' + err, ans_id);
                    }
                } else {
                    do_set_answer(statuses.error, ans_leg + ': code=' + xmlhttp.status + ', ans=' + xmlhttp.responseText, ans_id);
                }
                if (callback_data.hasOwnProperty('mark_update')) {
                    callback_data.mark_update();
                }
                if (callback_data.hasOwnProperty('do_once_any_case') && callback_data['do_once_any_case']) {
                    return;
                }
                let timeout = xmlhttp.status >= 200 ? 5000 : 15000;
                setTimeout(do_data_load, timeout, callback_data);
            }
        };
        if (callback_data.hasOwnProperty('post_data')) {
            xmlhttp.send(callback_data.post_data);
        } else {
            xmlhttp.send();
        }
    }
