CSGOLoungeLive

A csgolounge.com betting tool and enhancer.

目前為 2015-03-31 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name          CSGOLoungeLive
// @namespace     CSGOLoungeLive
// @author        soma
// @description   A csgolounge.com betting tool and enhancer.
// @include       http://csgolounge.com/
// @include       http://csgolounge.com/#
// @exclude       http://*.csgolounge.com/
// @require       http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
// @version       0.2.1
// @icon          http://cloud-4.steamusercontent.com/ugc/594764304137589098/69F7EBE2735C366C65C0B33DAE00E12DC40EDBE4/
// @grant         GM_addStyle
// @grant         GM_getValue
// @grant         GM_setValue
// @grant         GM_xmlhttpRequest
// @grant         GM_getResourceText
// ==/UserScript==

/* Note: You are ALLOWED to edit and/or modify this script if belonging credits are given and you have informed the author BEFORE publishing the modified version.
 *       You are NOT ALLOWED to sell whole or any parts of this script.
 *       (cl) 2015 - soma.
 *       For further information contact soma @steam id: "somq" or on reddit.
 * */
GM_addStyle(' \
body {background-image: none;}\
.shownotav-btn:active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.3); text-decoration: none; background-color: #eeeeee; border-color: #cfcfcf; color: #d4d4d4; } \
.shownotav-btn:hover, .button:focus, #switchmainviewa:hover, #switchmainviewa:hover { background-color: #f6f6f6; color:#999;} \
.shownotav-btn { letter-spacing: 5px; font-size: 16px; height: 50px; line-height: 40px; border-radius: 4px; background-color: #eeeeee; border: medium none; box-sizing: border-box; color: #666666; cursor: pointer; transition-duration: 0.3s; transition-property: all;; float: left; height: 40px; text-align: center; } \
.shownotav { width: 100%; padding: 0 50px; } \
main section.box {width: 68%;};\
.smallfont {font-size: 12px;} a.smallfont:hover {color:#666;}.teamadetails {width: 45%; float: left; text-align: center} .teambdetails{width: 45%; float: left; text-align: center} \
.vsdetails{width: 10%; float: left; text-align: center;font-size: 16px;} .detailsbox {float: left; margin: 16px 2%; width: 78%;font-size: 14px;}.teamtext {font-size:16px} \
.matchheader-spacer { font-size:0.8rem; margin: 0 5px; float: left;}\
.c-loading {background-image: url("http://img4.hostingpics.net/pics/5276773011.gif"); height: 100px; position: absolute; width: 100px;}\
.matchleft {min-height: 70px;box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 1px 0 rgba(255, 255, 255, 0.5); border-radius: 8px; padding: 5px 0;max-width:1555px; width:63%;} section.box {width:98%; max-width:1430px;} .matchctn{float:left;width: 98%;} \
#c-overlay { background-color: rgba(0, 0, 0, 0.5); height: 100%; left: 0; position: absolute; top: 0; width: 100%; z-index: 10; }\
#switchmainview {float: right; display:none;}\
#mainloadingbar {margin-left: auto; margin-right: auto; width: 260px;}\
.progress { box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 1px 0 rgba(255, 255, 255, 0.5); margin: 10px 30px; width:200px; background: none repeat scroll 0 0 #ebebeb; border-left: 1px solid transparent; border-radius: 10px; border-right: 1px solid transparent; height: 20px;}\
.progress > span {background: linear-gradient(to bottom, #f0f0f0, #dbdbdb 70%, #cccccc) repeat scroll 0 0 #cccccc; border-color: #bfbfbf #b3b3b3 #9e9e9e; border-image: none; border-radius: 10px; border-style: solid; border-width: 1px; box-shadow: 0 1px rgba(255, 255, 255, 0.3) inset, 0 1px 2px rgba(0, 0, 0, 0.2); float: left; height: 18px;line-height: 4px; margin: 0 -1px; min-width: 30px; position: relative;text-align: right;} \
.progress > span > span { line-height: 17px; color: rgba(0, 0, 0, 0.7); font-size: 11px; font-weight: bold; padding: 0 8px; text-shadow: 0 1px rgba(255, 255, 255, 0.4);} \
.mb-loading { height: 25px;text-align: center; background: url("http://img11.hostingpics.net/pics/279433ajaxloader3.gif") no-repeat scroll center center rgba(0, 0, 0, 0);} \
.rounded-btn1{ display: block;width:40px; height:40px; border-top:2px solid #fff; border-radius:50%; background-color:#EEEEEE; background: linear-gradient(#EDEAE1,#CDC8B5); text-align:center; box-shadow: 0 5px 2px 3px rgba(158, 158, 158, 0.4), 0 3px 5px #B7B6B6, 0 0 0 2px #BBB7AE, inset 0 -3px 1px 2px rgba(186, 178, 165, 0.5), inset 0 3px 1px 2px rgba(246, 245, 241, 0.3); cursor:pointer; } .rounded-btn1:active{border-radius:50%; border-top:none; border:1px solid #BAB7AE; background-color:#EEEEEE; text-align:center; color:#BAB7AE; text-shadow: 0 1px 1px white, 0 1px 1px #BAB7AE; box-shadow: 0 0 0 0 #BBB7AE; } .rounded-btn1 span { font-size:30px; color:#666; text-shadow:2px 2px 0 rgba(255, 255, 255, 0.9);}\
.feeds {text-shadow: 1px 1px 0 #e5e5e5;margin: 16px 1%; font-size:14px;}\
#feedsbox { width:30%; display: block; float: left; margin: 10px 0.5%;}\
.feeds-header {background: url("http://img11.hostingpics.net/pics/396420iconrssgrey.png") no-repeat scroll 0 0 / 33px auto rgba(0, 0, 0, 0)}\
.cleanleft { float:left;}\
.padding20 {padding-left: 20px;}\
.feedstitle { height: 46px; opacity: 0.7; padding: 1%; text-align: center; text-decoration: underline; }\
#hltvfeed .feedstitle {background: url("http://img15.hostingpics.net/pics/49901496Zhddu.jpg") no-repeat scroll 50% center rgba(0, 0, 0, 0);}\
#redditfeed .feedstitle {background: url("http://img15.hostingpics.net/pics/464286reddit.png") no-repeat scroll 50% center rgba(0, 0, 0, 0);}\
#gosugamersfeed .feedstitle {background: url("http://img15.hostingpics.net/pics/241137gglogo.png") no-repeat scroll 50% center rgba(0, 0, 0, 0);}\
.feeds li { box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 1px 0 rgba(255, 255, 255, 0.5); padding: 1%; } \
.feedslinks-box {margin: 0 2% 16px;padding-top: 5px;}\
.feedlink a {display: block;}\
.feedlink a:hover {border-radius: 2px; box-shadow: 1px 0px 0px 1px #999; display: block; opacity: 0.8; transition: 0.5s;}\
.main-feedbox {  background-color: #bbb;border-radius: 5px;float: left;box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 1px 0 rgba(255, 255, 255, 0.5);width: 100%;}\
.line2a { padding-left: 10px; text-align: center;font-size: 14px;}\
.line2b { padding-right: 10px; text-align: center;font-size: 14px;}\
.matchbox-summary { float: left; font-size: 12px; margin: 16px 0; width: 15%;}\
.expandmatch-btn { color: #ddd; position:absolute; height: 20px; padding-left: 7px; font-size:20px;}\
.expmatchbtn-ctn { float: right; height: 25px; width: 25px;}\
.infosbelow-lr {width: 35%; float: left;}\
.infosbelow-center { float: left; font-size: 14px; text-align: center; width: 30%; } \
.sumbox {text-align: center; background: #bababa; border-radius: 4px; float: left; margin: 2px 0; opacity: 0.9; padding: 4px 4px 4px 20px; border: 1px solid #9b9b9b;}\
.suminfo {}\
.suminfo-info{background: url("http://img11.hostingpics.net/pics/344354iconinfov3.png") no-repeat scroll 2px center / 14px auto #ababab}\
.suminfo-bet{background: url("http://img15.hostingpics.net/pics/666500Dice.png") no-repeat scroll 2px center / 16px auto #ababab}\
a .suminfo-info:hover { background: url("http://img11.hostingpics.net/pics/344354iconinfov3.png") no-repeat scroll 2px center / 14px auto #D7D7D7; transition: 0.5s; opacity: 0.9;}\
a .suminfo-bet:hover { background: url("http://img15.hostingpics.net/pics/666500Dice.png") no-repeat scroll 2px center / 16px auto #D7D7D7; transition: 0.5s; opacity: 0.9;}\
.feedloading {background: url("http://img4.hostingpics.net/pics/356667712.gif") no-repeat scroll 3px center transparent; height: 30px; width: 30px; display: block; position: absolute; margin-left: 23%; margin-top: 1%;}\
aside#submenu {float:left;opacity: 0.9;border-radius: 0 0 10px;}\
main {padding-right:0;}\
#submenutoggle { background: none repeat scroll 0 0 #252525; float: right; font-size: 30px; height: 40px; opacity: 1; text-align: center; width: 200px; }\
aside#submenu > nav {margin:0}\
#shortsmb {  background: none repeat scroll 0 0 #252525; border-radius: 0 0 6px; float: left; font-size: 20px; opacity: 0.7; padding: 5px 10px 10px 5px; text-align: center;}\
#shortsmblink { color: #ff8a00;}\
.matchloading { background: url("http://img4.hostingpics.net/pics/5276773011.gif") no-repeat scroll 0 0 / 40px auto #cbcbcb; border-radius: 20px; height: 40px; left: 2%; margin: 5px; opacity: 0.6; width: 40px; }\
.matchloading-ctn { float: left; height: 50px; margin: 5px; position: absolute; width: 50px; }\
#infobox-wrapper {  background: none repeat scroll 0 0 #eee; border-radius: 5px 5px 0 0; bottom: 0; opacity: 0.9; padding: 15px 15px 10px; position: fixed; right: 50px; width: 430px; }\
.infobox-ctn {  background: none repeat scroll 0 0 #fff; border: 1px solid #ccc; border-radius: 3px; padding: 10px; text-align: center; }\
#settings-aliases {padding:5px 0;}\
 label { margin-left: 5px; float:right; font-size: 12px;background: none repeat scroll 0 0 rgb(138, 138, 138); border-radius: 14px; box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.1) inset, 0 -1px 0 0 rgba(0, 0, 0, 0.1) inset; color: #fff; cursor: pointer; display: inline-block; font-style: normal; font-weight: bold; height: 20px; line-height: 20px; position: relative; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); transition: all 1s ease-in 0s; width: 50px; } \
 label i { background: none repeat scroll 0 0 rgb(255, 255, 255); border-radius: 20px; box-shadow: 0 -3px 3px 0 rgba(0, 0, 0, 0.1) inset, 0 -1px 1px 0 rgba(255, 255, 255, 0.4) inset, 0 2px 0 0 rgba(0, 0, 0, 0.2); display: block; height: 20px; position: absolute; right: 30px; top: 0px; transition: all 100ms ease 0s; width: 20px;} \
 label i:before {  background: none repeat scroll 0 0 rgb(239, 239, 239); border-radius: 12px; box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.1) inset; content: ""; display: block; height: 8px; left: 50%; margin: -4px 0 0 -4px; position: absolute; top: 50%; width: 8px;} \
 label:active i:before { box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.3); } \
 label:before { content: "off"; margin-left: 20px; text-transform: uppercase; transition: all 200ms ease; } \
 input[type=checkbox]:checked ~ label:before { content: "on"; text-transform: uppercase; margin-right: 30px; margin-left: 5px; } \
 input[type=checkbox]:checked ~ label{ background: rgb(141,173,51); background: radial-gradient(center, ellipse cover, rgba(141,173,51,1) 0%, rgba(146,178,55,1) 24%, rgba(157,187,64,1) 55%, rgba(166,194,78,1) 100%); } \
 input[type=checkbox]:checked ~ label i { right: 0px; } \
 input[type=checkbox] { display:none; }\
 .matchmain { text-shadow: 0 1px 1px #ffffff; }\
.match {box-shadow:1px 2px 2px 2px #888;}\
.title { color: #999; float: left; position: relative; width: 98%;padding: 1% 1% 0;margin-left:0;text-transform: none;} \
.title a{ color: #999;height: 40px;} \
.title:hover a { color: inherit; text-shadow: inherit;}\
.matchheader {border-top: 1px solid #ccc; border-radius: 10px;margin-bottom:4px;background:#ccc;}\
#mainheader { font-weight: 300; line-height: 16px;min-height: 40px;float:left; color: #777;font-size: 12px;width: 100%;border: 1px solid #ccc;}\
#mainheader .nomatchesfound {text-align:center;}\
#mainheader li { margin: 3px; padding: 2px;}\
.mainheader-c {}\
 .bets-header {background:url("http://cdn.csgolounge.com/img/bets.png") no-repeat;}\
 .mh-boxes {}\
 .mh-left {width:20%;float:left;padding:2px;}\
 .mh-center {width:50%;padding: 0 2px; margin:0 auto; text-align:center;}\
 .mh-right {width:175px;float:right;padding: 0 2px;}\
 #matchescount {}\
#current-matchescount {font-weight:bold;}\
li.sticker { background: none repeat scroll 0 0 #e0e0e0; border-radius: 3px; box-shadow: 1px 1px 1px 1px #ccc; text-shadow: 0 1px 0px #fff;} \
.austatus-title { font-weight: bold; text-align: center;}\
.austatus-inner { font-weight: normal; text-align:left; margin-top: 5px;}\
.numofm {font-weight:bold;}\
.au-lasttime { float:right; font-weight:bold;color: #8a8a8a;}\
.au-timeleft { float:right; font-weight:bold;color: #8a8a8a;}\
.scriptinfo-header {};\
');
// Grey scheme: Foreground color = #333333 // Background color = #bbbbbb
//console.log(GM_info.scriptWillUpdate);
//console.log(GM_info.version);
var scriptVersion = GM_info.script.version;
//console.log(version);
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
//var settings = JSON.parse(localStorage.getItem("csglLiveSettings"));
//settings.updateDelay = 500000;
//localStorage.removeItem("csglLiveSettings")
console.log(GM_info )


var versionCS = GM_info.script.version;
var newVersionCS = (localStorage['csgllive_lastversion'] != versionCS);
if(newVersionCS) {
        localStorage['csgllive_lastversion'] = versionCS;
        alert('newversion'+versionCS);
}

//localStorage.getItem('csgllive_lastversion')

// Global settings
var settings = {
    "debug": {
        "global": "0",
        "feeds": "0"
    },
    "matchBoxStatus": "0", // Main view, boxes open, closed. disabled until everything is done
    "mainMenuStatus": "0", // 1 Show, 0 Hide main menu
    "updateDelay": "300000", // 30 seconds
    "defaultTimeout": "10000", // 10 seconds
    "switches": {
        "completeinit": true,
        "feeds": true,
        "autoupdate": true
    }
};
localStorage.setItem("csglLiveSettings", JSON.stringify(settings));
if (!is_chrome) {
    var baseUrl = window.location.href;
    var regexp = /.*\/(.*?)$/;
    var match = regexp.exec(baseUrl);
    if (match[1] === '#')
        var baseUrl = baseUrl.replace('#', '');
} else { var baseUrl = "http://csgolounge.com/"; }

var globalJobStatus = []; // global status for job to track if they are finished or not.
var globalData = {}
if (localStorage.getItem("csglLiveSettings") !== null) {
    settings = JSON.parse(localStorage.getItem("csglLiveSettings"))
}

// debug log if activated 
if (!is_chrome) {
    _log = (function (undefined) { // if firefox
        var Log = Error; //  proper inheritance...?
        Log.prototype.write = function (args) {

            var lineNum = extractLineNumberFromStack(this.stack);
            var lineNumberStr = [[lineNum]];

            args = args.concat(lineNumberStr);
            args = sortArray(args);
            //                console.log(args);
            if (console && console.log) {
                if (console.log.apply) {
                    console.log.apply(console, args);
                } else {
                    console.log(args);
                } // nicer display in some browsers
            }
        };
        var extractLineNumberFromStack = function (stack) {

            var lineNum = stack.split('\n')[1];
            var lineNum = lineNum.split(' (')[0].substring(0, lineNum.length - 1);
            var lineNum = lineNum.split(':')[3].substring(0, lineNum.length - 1);
            return lineNum;
        };
        var sortArray = function (arrayTosort) { // swap 1st and last value.
            argsNew = [];
            for (var i = 0; i < arrayTosort.length; i++) {
                var j = i + 1;
                argsNew[j] = arrayTosort[i];
            }

            var lastItem = argsNew.pop();
            argsNew[0] = lastItem;
            return argsNew;
        };
        return function (params) {

            if (typeof settings.debug.global === typeof undefined || settings.debug.global === '0')
                return;

            Log().write(Array.prototype.slice.call(arguments, 0));
        };

    })();
} else {
    _log = function (args) {
        console.log(args);
    }
}
pLog = _log;
/* log tool */
window.log = function () {
    log.history = log.history || [];   // store logs to an array for reference
    log.history.push(arguments);
    if (this.console && settings.debug.global === '1') {
        console.log(Array.prototype.slice.call(arguments));
    }
};
l = function (args) {
    console.log(args);
}
_l = function (args) {
    console.log(args);
}
/* Global Class - wrap basically every workers jobs - process detailled below... */
function globalClass(worker) {
    this.worker = worker;
    this.job = "default Job"
    this[this.worker] = {"data": []};
    console.log("globalClass", this.worker, this[this.worker]);

    // matches ajax req errors & loading
    this.loading = {};
    this.loading.matchdiv = '<div class="matchloading-ctn"><div class="matchloading"></div></div>';

    // If error on retrieve is returned by matches ajax request: // errors.JOB.STRING
    this.errors = {};
    this.errors.match = {};
    this.errors.match.toAppendFirstPart = '<div class="detailsbox error">There was an error retrieving the data (';
    this.errors.match.toAppendLastPart = ')...<a href="#" class="maindata-retrieve">Retrieve manually</a></div>';
    this.errors.match.aborted = this.errors.match.toAppendFirstPart + 'Aborted' + this.errors.match.toAppendLastPart;
    this.errors.match.timedOut = this.errors.match.toAppendFirstPart + 'Timed out' + this.errors.match.toAppendLastPart;
    this.errors.match.error = this.errors.match.toAppendFirstPart + 'Error' + this.errors.match.toAppendLastPart;
    this.errors.match.RetrieveFailedMatches = " item failed to load. <a href='#' class='retrieve-failedmatches'>Retrieve missing matches</a> ";

    this.feeds = {
        "data": [
            "reddit", "hltv"
        ],
        "feedsDatas": {
            "reddit": {
                "url": "https://vast-harbor-8484.herokuapp.com/api?feed=reddit",
                "datas": ""
            },
            "hltv": {
                "url": "https://vast-harbor-8484.herokuapp.com/api?feed=hltv",
                "datas": ""
            }
        }
    };

    this.feedbox = '<section id="feedsbox"><div class="title"><div id="secondheader" class="feeds-header mainheader-c">&nbsp;<div class="cleanleft padding20"><strong>Feeds</strong> </div></div></div></section>';

    this.propsContainers = {
        "bestOf": ".infosbelow-center",
        "dateRaw": ".dateRaw",
        "ipstatus": "",
        "itemplaced": "",
        "mainstream": "",
        "matchNameA": ".teamtext:eq(0) b",
        "matchNameB": ".teamtext:eq(1) b",
        "msstatus": "",
        "peopleItemsNum": ".peopleItemsNum",
        "teamAReward": ".infosbelow-lr span:eq(0)",
        "teamAperc": ".teamtext:eq(0) i",
        "teamBReward": ".infosbelow-lr span:eq(1)",
        "teamBet": "",
        "teamBperc": ".teamtext:eq(1) i",
        "timeLeft": ".matchheader .whenm:eq(0)",
        "timeRaw": ".timeRaw",
        "valueBetA": "",
        "valueBetB": ""
    }
    this.arrow = {}
    this.arrow.up = '<span style="color: green;">&#8593;</span>';
    this.arrow.down = '<span style="color: red;">&#8595;</span>';
} /* ! globalClass(worker)*/


globalClass.prototype.initGlobalProcess = function () {
    _log('*** Global INIT for worker ' + this.worker + ' ***');

    var dfd = new jQuery.Deferred();
    return dfd.resolve(this);

}; // !initGlobalProcess
globalClass.prototype.error = function (e) {
    alert('something really bad happened... ! :(');
};
globalClass.prototype.done = function (e) {
    console.log(this.worker, 'has finished his jobs.', this);
    if (this[this.worker].data.length > 0 && this[this.worker].loadingStatus.globalMonitor.error === 0) { // push worker name in globalJobStatus array if there are data and loading succeed with no errors.
        globalJobStatus.push(this.worker);
    }

    if (this.worker === "feeds" || this.worker === "initialization") { // check when both worker has ended to init updatePage
        if (this.worker === "initialization") {
            globalData.currentData = this.initialization.data;
        }
//        localStorage.setItem("currentData", JSON.stringify(this.initialization.data));
        if (globalJobStatus.length === 2 && globalJobStatus.indexOf("initialization") > -1 && globalJobStatus.indexOf("feeds") > -1) {
            console.log('both workers initialization and feeds have finished their jobs');
            // We can - start finding occurences between feeds and matches - start page updating.
//              console.log(this.feeds.feedsDatas);
            globalData.currentData = this.initialization.data; // feed global obj with current matches data


//            var initUpdatePage = new globalClass('UpdatePage'); // init updateData worker
//            initUpdatePage.initGlobalProcess();
        }
    }
    var dfd = new jQuery.Deferred();
    return dfd.resolve(this);
};
globalClass.prototype.initPageView = function () {
    _log('*** init Page View ***');
    var self = this;

    /* MAIN STYLE*/
    var mainStyle = $('head link[type="text/css"]').attr('href');
    var mainStyle = mainStyle.replace(/\d+$/, '');

    if (mainStyle != '//cdn.csgolounge.com/css/gray.min.css?') {
        $.ajax({
            method: 'GET',
            url: 'ajax/setSkin?skin=1',
            success: function (response) {
                console.log(response);
            }
        });
        $('head link[type="text/css"]').attr('href', "//cdn.csgolounge.com/css/gray.min.css?");
    }

    // Main view, boxes open, closed.
    if (settings.matchBoxStatus === '0') {
//        localStorage.setItem('matchBoxStatus', settings.matchBoxStatus);
        this.matchBoxStatus = ' style="display:none;"';
        var btnMatchBoxStatus = '+';
    } else if (settings.matchBoxStatus === '1') {
//        localStorage.setItem('matchBoxStatus', settings.matchBoxStatus);
        this.matchBoxStatus = ' style="display:block;"';
        this.btnMatchBoxStatus = '-';
    } else {
        this.matchBoxStatus = ' style="display:block;"';
    }

    // hide main trade box
    $('#tradelist').parent().hide();
    $('#tradelist').hide();

    // Hide not available, add button
    var firstna = $('.matchmain .notavailable:first').parent();
    firstna.nextAll().andSelf().wrapAll("<div id='sh-na' style='display:none;'></div>")
            .parent().before('<a href="#" class ="shownotav-btn shownotav"><span>Show closed matches</span></a>');
    $("body").on("click", "a.shownotav-btn", function (e) {
        $('a.shownotav-btn').remove();
        $('#sh-na').slideDown('slow');
        e.preventDefault();
    });

    // Page Header
    $('.title, #bets').removeAttr('style');

    //matchheader
    $('.title:eq(1)').html('<div id="mainheader" class="bets-header mainheader-c"></div>');
    $('#mainheader').append('<div class="mh-boxes mh-left"><ul></ul> </div>');
    $('#mainheader').append('<div class="mh-boxes mh-right"><ul></ul></div></div>');
    $('#mainheader').append('<div class="mh-boxes mh-center"><ul></ul></div>');
    $('.mh-left ul').append('<li class="sticker matchesav"></li>');
    if (settings.switches.autoupdate === true) {
        $('.mh-left ul').append('<li class="sticker austatus-title">Auto Update status<span class="austatus-inner"><ul><li>Last update: <span class="au-lasttime">-</span></li><li>Next update in: <span class="au-timeleft">-</span></li></ul></span>');
    }
    $('.mh-center').prepend('<span class="scriptinfo-header">csgl live version: ' + scriptVersion + ' - no update available - <a href="#">reddit</a> - <a href="#">steam</a> - <a href="#">donation</a></span>');
    //matchheader
    $('.mh-right ul').append('<li>Matches Infos: <input type="checkbox" id="completeinit-switch" /> <label for="completeinit-switch" > <i></i> </label></li>');
    $('.mh-right ul').append('<li>Feeds: <input type="checkbox" id="feeds-switch" /> <label for="feeds-switch" > <i></i> </label></li>');
    $('.mh-right ul').append('<li>Auto Update: <input type="checkbox" id="autoupdate-switch" /> <label for="autoupdate-switch"> <i></i> </label></li>');

    // Switches status
    $('#completeinit-switch').attr('checked', settings.switches.completeinit);
    $('#feeds-switch').attr('checked', settings.switches.feeds);
    $('#autoupdate-switch').attr('checked', settings.switches.autoupdate);

    $("#mainheader").on("click", "input#completeinit-switch", function (e) {
        if ($('input#completeinit-switch').is(":checked") === true) {
            settings.switches.completeinit = true;
        } else {
            settings.switches.completeinit = false;
            settings.switches.autoupdate = false;
            $('#autoupdate-switch').attr('checked', settings.switches.autoupdate);
        }
        localStorage.setItem("csglLiveSettings", JSON.stringify(settings));
    });
    $("#mainheader").on("click", "input#feeds-switch", function (e) {
        settings.switches.feeds = $('input#feeds-switch').is(":checked") ? true : false;
        localStorage.setItem("csglLiveSettings", JSON.stringify(settings));
    });
    $("#mainheader").on("click", "input#autoupdate-switch", function (e) {
        if ($('input#completeinit-switch').is(":checked") === false) {
            $('#autoupdate-switch').attr('checked', false);
            alert('Turn on "matches infos" first.')
        } else {
            settings.switches.autoupdate = $('input#autoupdate-switch').is(":checked") ? true : false;
            localStorage.setItem("csglLiveSettings", JSON.stringify(settings));
        }
    });
    // Big Main Switch Button
    //$('#mainheader').append('<div id="switchmainview"><a href="#" id="switchmainviewa" class="rounded-btn1"><span>' + btnMatchBoxStatus + '</span></a></div>')

    $("#switchmainview").on("click", "a#switchmainviewa", function (e) {
        $(".detailsbox").slideToggle("fast", function () {
            $("#switchmainviewa span").text($('.detailsbox').is(':visible') ? "-" : "+");
        });
        e.preventDefault();
    });

    // Boxes expander
    $("#bets").on("click", "a.expandmatch-btn-a", function (e) {
        var $alinktext = $(e.target);
        var $detailsbox = $(e.target).parents().eq(2).find('.detailsbox');
        $detailsbox.slideToggle("fast", function () {
            $alinktext.text($detailsbox.is(':visible') ? "-" : "+");
        });
        e.preventDefault();
    });
    // SubMenu
    $('aside#submenu').prepend('<a id="submenutoggle"><span href="#" id="submenutogglelink">&#8592;</span></a>');
    $("#submenu").after('<a id="shortsmb" style="display:none;"><span id="shortsmblink" href="#">&#8600;</span></a>');
    if (settings.mainMenuStatus == '0') {
        $('aside#submenu').hide();
        $('#shortsmb').show();
    }

    $("body").on("click", "a#shortsmb", function (e) {
        $('#shortsmb').hide('fast');
        $("aside#submenu").show("slide");
        settings.mainMenuStatus = '1';
        localStorage.setItem("csglLiveSettings", JSON.stringify(settings));
    });
    $("#submenu").on("click", "a#submenutoggle", function (e) {
        $("aside#submenu").hide("slide", function () {
            $('#shortsmb').show();
            settings.mainMenuStatus = '0';
            localStorage.setItem("csglLiveSettings", JSON.stringify(settings));
        });
    });

    // Error link when a matchbox has failed to retrieve matchInfos
    // NOTE: USE initialization worker FOR THIS
    $(".match").on("click", "a.maindata-retrieve", function (e) {
        var selector = $(this).closest('.matchmain');
        selector.find('.error').remove();
        CompleteInitialization.call(this, this.worker, selector)
        e.preventDefault();
    });

    $("#error-matchesload").on("click", "a.retrieve-failedmatches", function (e) {
        var selector = self[self.worker].loadingStatus.globalMonitor.mustRetry;
        $('#error-matchesload').empty();
        $(selector).each(function (index, value) {
            value.find('.error').remove();
        });
        CompleteInitialization.call(this, this.worker, selector)
        e.preventDefault();
    });

    // infobox
    $('main').append('<div id="infobox-wrapper" style="display: none;"><div class="infobox-ctn"></div></div>');

    // show trades
    $('#menu').append('<a href="#" class="showtrades"><img alt="Show trades" src="//cdn.csgolounge.com/img/my_trades.png">Show trades</a>');
    $("#menu").on("click", "a.showtrades", function (e) {
        $('.box:eq(1)').toggle(); // matchbox
        $('.box:eq(0)').fadeToggle('slow'); // trade box
        $('.box:eq(0) #tradelist').toggle() // tradebox inner
        e.preventDefault();
    });

    _log('-init page view done.');
    var dfd = new jQuery.Deferred();
    return dfd.resolve(this);
};

/* Loop through dom .matchmain and retrieve infos */
globalClass.prototype.parseMainPage = function (selector, rawData) {
    _log('*** parse Main Page ***');

    var data = (typeof rawData !== "undefined") ? rawData : 'body';

    if (typeof selector !== 'undefined' && selector !== "") {
        var matchesCtn = selector;
    } // If user has clicked to manually retrieve infos of a specific match
    else {
        var matchesCtn = $(data).find('.matchmain .match').not('.notavailable').parent();
    } //if not, selector is every match available on the page
    var csgl = {"data": []};// global object, containing basically every data of every match.

    if (matchesCtn.length >= 1) {   // iterate through every matchmain box, find data, store it in csgl obj.
        $(matchesCtn).each(function (index, value) {

            var matchUrlDest = $(this).find('a').attr('href');
            var matchId = matchUrlDest.replace('match?m=', '').replace("predict?m=", "");
            var matchUrl = baseUrl + matchUrlDest;
            var matchCtn = $(this).find('a[href="match?m=' + matchId + '"]').closest('.match');
            var matchPercA = $(this).find('a[href="match?m=' + matchId + '"] div.teamtext:eq(0) i').text();
            var matchPercB = $(this).find('a[href="match?m=' + matchId + '"] div.teamtext:eq(1) i').text();
            var matchNameA = $(this).find('a[href="match?m=' + matchId + '"] div.teamtext:eq(0) b').text();
            var matchNameB = $(this).find('a[href="match?m=' + matchId + '"] div.teamtext:eq(1) b').text();

            matchCtn.append('<div class="matchloading-ctn"><div class="matchloading"></div></div>'); // init loading display

            var csglMatchData = {
                matchUrl: matchUrl,
                matchId: matchId,
                matchCtn: matchCtn,
                teamAperc: matchPercA,
                teamBperc: matchPercB,
                matchNameA: matchNameA,
                matchNameB: matchNameB
            };
            csgl.data.push(csglMatchData);
        }); // matches basic data retrieving has finished.

        this[this.worker].data = csgl.data;    // Obj = this.worker.data[matches]

//        localStorage.setItem('csgl', JSON.stringify(csgl));

        // success
        _log('-parseMainPage success', this[this.worker].data);

        var dfd = new jQuery.Deferred();
        return dfd.resolve(this);
    } else {
        // escaped
        _log('parseMainPage escaped, no matches found'); // No matches has been found, append a message and retrieve the feed
//        updateLoading('', '1'); // Set progress bar to 100%
        $('#mainheader').append('<div class="nomatchesfound"><br />There are currently no matches to bet on ! ;( <br /> Try checking later...</div>');
    }

};
// gather and append global infos
globalClass.prototype.globalInfos = function () {
    _log('*** global infos ***');
    var numberOfMatchesS = $('body').find('.matchmain .match').not('.notavailable').parent().length; // ??!

    var dfd = new jQuery.Deferred();
    return dfd.resolve(this);
};
globalClass.prototype.monitorWorker = function (jobStatus, container, id) { // jobStatus = error || success
    _log('... currently monitoring "' + this.worker + '" worker ...');
    this[this.worker].loadingStatus.globalMonitor[jobStatus] = ++this[this.worker].loadingStatus.globalMonitor[jobStatus]; // monitor global responses status to count how many succeed and failed. }
    if (jobStatus === "error") {
        (this[this.worker].loadingStatus.globalMonitor.mustRetry).push(container);
    }
};
globalClass.prototype.initLoading = function () {    // init loading
    _log('... Init Loading ...');
    console.log("obj this[this.worker]:", this.worker, this[this.worker]);
    var data = this[this.worker].data;
    if (data === "undefined" || data === 0) {
        dataLength = 1
    }

    if (typeof data === "object") {
        var dataLength = (Object.getOwnPropertyNames(data).length) - 1;
    } // USEFUL 'TILL I FIX THE WORKER OBJ FORMAT ?
    else {
        var dataLength = data.length;
    }

    this[this.worker].loadingStatus = {// loading vars
        "index": 0,
        "totalItemsToLoad": dataLength,
        "globalMonitor": {"error": 0, "success": 0, "mustRetry": []}  // index to monitor how many ajax requests succeed
    };

    // VIEW
    if (this.worker === "feeds") { // append feeds container and init loading gif
        $('main').append(this.feedbox);
        $.each(data, function (index, value) {
            $('main #feedsbox').append('<article id="' + value + 'feed-ctn" class="feeds standard"> <div class="main-feedbox" id="' + value + 'feed"><span id="' + value + '-loading" class="feedloading" style="display:none;"></span><div class="feedstitle"> </div> <div class="feedslinks-box"><ul></ul></div> </div> </article>');
        });
        $('.feedloading').fadeIn('fast');
    } else if (this.worker === "initialization" || this.worker === "basicInit") {    // matches count and loading bar
        if ($('#matchescount').length === 0) {
            $('#mainheader .mh-center ul').append('<li><div id="matchescount"><span id="current-matchescount">0</span> / <span id="total-matchescount"></span> matches to bet.<span id="error-matchesload"> </span></div></li>');
            $('#mainheader .mh-center ul').append('<li><div id="mainloadingbar"><div class="progress"><span style="width: 0%;"><span>0%</span></span></div></div></li>');
        }
        // matchescount
        var numberOfMatchesS = $('body').find('.matchmain .match').not('.notavailable').parent().length;
        $('.matchesav').html(' &#149; <span class="numofm">' + numberOfMatchesS + '</span> matches available.');
        $('#mainheader #matchescount #total-matchescount').html(numberOfMatchesS);

    } else {    // any worker VIEW
        console.log(this[this.worker])

    }
    console.log("initloadingEND", this[this.worker].loadingStatus)

    var dfd = new jQuery.Deferred();
    return dfd.resolve(this);
}

// Ajax requests prototype, do the worker requests, parse the data, return whatever needed
globalClass.prototype.ajaxCalls = function (worker, job, url, id, container, timeout) {
    _log('... ajaxCalls ...');
    _log("Request sent for worker:", worker, " url: ", url, " id: ", id, " container: ", container);

    if (typeof timeout === "undefined") {
        timeout = settings.defaultTimeout;
    }

    this.genericCall = function () {
        var self = this;
        _log('ajax req for: ', worker, ' @: ', url, container);
        return $.ajax({
            method: 'GET',
            url: url,
            timeout: timeout,
            success: function (data) {   // Request complete, parse data
//                _log('request complete for: url:', url, ' id: ', id,' container:', container, 'RESULT=', data);
                _log("response received for worker:", worker, "url;", url)
            },
            onabort: function (data) {
                _log('onabort error throwed for request=> url:', url, ' id: ', id, ' container:', container, 'RESULT=', data);
            },
            ontimeout: function (data) {
                _log('ontimeout error throwed for request=> url:', url, ' id: ', id, ' container:', container, 'RESULT=', data);
            },
            onerror: function (data) {
                _log('onerror error throwed for request=> url:', url, ' id: ', id, ' container:', container, 'RESULT=', data);
            }
        });
    };

//    if (worker === 'initialization' || worker === 'feeds') { // if there are other requests type to add, keep this worker in a condition statement...
    return this.genericCall();
//    }

};
// Global INIT Parse each match page request
globalClass.prototype.parseMatchPageData = function (worker, job, url, id, container, data) {
    _log('... parseMatchPageData ...');
    _log('parsing data for url:', url, ' id: ', id, ' container:', container);
    
    var self = this;
    var $d = $(data);

    var tar = '.box-shiny-alt:eq(0) .full .half:eq(0)';
    var tar = $d.find(tar);
    var teamAReward = tar.length > 0 ? tar.html().split("<br>")[1] : '';

    var tbr = '.box-shiny-alt:eq(0) .full .half:eq(1)';
    var tbr = $d.find(tbr);
    var teamBReward = tbr.length > 0 ? tbr.html().split("<br>")[1] : '';

    var vba = '.box-shiny-alt:eq(0) .full .half:eq(0)';
    var vba = $d.find(vba);
    var valueBetA = vba.length > 0 ? vba.html().split("<br>")[2] : '';

    var vbb = '.box-shiny-alt:eq(0) .full .half:eq(1)';
    var vbb = $d.find(vbb);
    var valueBetB = vbb.length > 0 ? vbb.html().split("<br>")[2] : '';

    var tl = '.box-shiny-alt:eq(0) .half:eq(0)';
    var tl = $d.find(tl);
    var timeLeft = tl.length > 0 ? tl.text() : '';

    var bo = '.box-shiny-alt:eq(0) .half:eq(1)';
    var bo = $d.find(bo);
    var bestOf = bo.length > 0 ? bo.text() : '';

    var t = '.box-shiny-alt:eq(0) .half:eq(2)';
    var t = $d.find(t);
    var time = t.length > 0 ? t.text() : '';

    var d = 'section.box:eq(0) .box-shiny-alt .half:eq(2)';
    var d = $d.find(d);
    var date = d.length > 0 ? d.attr("title") : '';

    var pin = 'section.box:eq(1) div.box-shiny-alt .full:eq(0)';
    var pin = $d.find(pin);
    var peopleItemsNum = pin.length > 0 ? pin.text() : '';
//            var matchDateFull = convertCsglDate(date, time);
//            var matchDateHuman = matchDateFull[1];
//            var matchDateRobot = matchDateFull[0];

    // Optional (itemplaced, mainstream)
    var ip = '.box-shiny-alt .full:eq(2)';
    var tb = '.box-shiny-alt a.active';
    if ($d.find(ip).length) {
        var itemplaced = $d.find(ip).html();
        var teamBet = $d.find(tb).index();
        if (teamBet == '1') {
            teamBet = 'a';
        }
        if (teamBet == '3') {
            teamBet = 'b';
        }
        var ipstatus = '1';
    } else {
        var itemplaced = 'No bet placed.';
        var ipstatus = '0';
        var teamBet = '0';
    }
    var ms = '#stream #mainstream';
    if ($d.find(ms).length) {
        var mainstream = $d.find(ms).html();
        var msstatus = '1';
    } else {
        var mainstream = 'No stream available';
        var msstatus = '0';
    }

    // Grep current matchId array in csgl.data object
    var result = $.grep(self[self.worker].data, function (element, index) {
        return element.matchId === id;
    });

    // Update csgl.data object by adding the new values we've just parsed.
    if (self[self.worker]) {
        $(self[self.worker].data).each(function (index, value) {
            if (value.matchId === id) {
                value.teamAReward = teamAReward;
                value.teamBReward = teamBReward;
                value.valueBetA = teamAReward;
                value.valueBetB = teamBReward;
                value.peopleItemsNum = peopleItemsNum;
                value.timeLeft = timeLeft;
                value.bestOf = bestOf;
                value.timeRaw = time;
                value.dateRaw = date;
//                        value.matchDateRobot = matchDateRobot;
//                        value.matchDateHuman = matchDateHuman;
                value.ipstatus = ipstatus;
                value.itemplaced = itemplaced;
                value.teamBet = teamBet;
                value.msstatus = msstatus;
                value.mainstream = mainstream;
            }

        });
    } // !if

    _log(self.worker + ' OBJ: ', self[self.worker]);
    // retrieve the object with data for the current "id"
    var result = $.grep(self[self.worker].data, function (e) {
        return e.matchId == id;
    });
    var data = result[0];

    _log('parseMatchPageData worker', worker, 'done for', url);

    var dfd = new jQuery.Deferred();
    return dfd.resolve(self, data, this);
};

globalClass.prototype.appendEachMatch = function (worker, job, url, id, container, data) {
    _log('*** appendEachMatch ***');
    _log("data", data);

    if (typeof (data.teamAReward) !== "undefined" && (data.teamAReward).length > 0) {
        //GATHER INFOS TO APPEND
        var nobetplaced = data.ipstatus === '0' ? data.itemplaced : '&nbsp;';
        var placedbet = data.ipstatus === '1' ? data.itemplaced : '&nbsp;';

        // infos Below TeamA vs TeamB
        var infosbelow = '<div class="infosbelow-lr infosbelow-tb"> <div class="line2a"><span title="csgolounge bet reward value">' + data.teamAReward + '</span></div> </div> <div class="infosbelow-center">' + data.bestOf + '</div> <div class="infosbelow-lr infosbelow-tb"> <div class="line2b"> <span title="csgolounge bet reward value">' + data.teamBReward + '</span> </div>';
        // Match box header (eg. time left, date cup etc...)
        var mDataHeaderSpacer = '<div class="matchheader-spacer">-</div>';
        var matchDataheader1 = ('<div class="whenm"> - <span class="dateRaw">' + data.dateRaw + '</span> - <span class="timeRaw">' + data.timeRaw + '</span></div>');
        var matchDataheader2 = ('<div class="whenm"><span class="peopleItemsNum">' + data.peopleItemsNum + '</span></div>');
        // matchheader (time left, date, additionnal info, cup)
        var $w = $('body').find('a[href="match?m=' + id + '"]').parents().eq(2).find('.matchheader .whenm');
        var $w2 = $('body').find('a[href="match?m=' + id + '"]').parents().eq(2).find('.matchheader');

        // APPEND
        // matchheader
        $w2.append(matchDataheader1 + mDataHeaderSpacer + matchDataheader2);

        // Infos below the TeamA vs TeamB part
        data.matchCtn.find('a:first').append(infosbelow);
        // SummaryBox (labels eg. "No bet placed" "hltv link" "reddit link" etc..."
        data.matchCtn.append('<div class="matchbox-summary"></div>');
        if (data.ipstatus == '0') {
            data.matchCtn.find('.matchbox-summary').append('<span class="sumbox suminfo-bet">No bet placed.</span>');
        } else {
            data.matchCtn.find('.matchbox-summary').append('<span class="sumbox suminfo-bet">A bet has been placed.</span>');
        }
        // Expand button
        data.matchCtn.append('<div class="expmatchbtn-ctn"><a class="expandmatch-btn-a"><span class="expandmatch-btn">+</span></a></div>');
        // DetailsBox (box to expand)
        data.matchCtn.append('<div class="detailsbox"' + this.matchBoxStatus + '>' + placedbet + '</div>');

        // MAINSTREAM
        // if (data.msstatus == '1') { 
        // data.matchCtn.append('<div class="detailsbox"><div class="mainstream-btn"><a href="#" > class="sh-stream">SHOW HIDE STREAM</a></div><div class="mainstream" style="display: none;">'+data.mainstream+'</div>')
        // }
        // $('.sh-stream').click(function(){
        // var $t = $(this).parents().eq(2);
        // alert($t.find('.mainstream'))
        // return false;
        // });

        _log('append done for id:', id);

    }
    // loading display
    data.matchCtn.find('.matchloading-ctn').remove();

    var dfd = new jQuery.Deferred();
    return dfd.resolve(this);
};

globalClass.prototype.updateLoading = function (loadingStatus) {
    var loadingStatus = this[this.worker].loadingStatus;
    if (this.worker === "feeds") {
        if (loadingStatus.index + 1 === loadingStatus.totalItemsToLoad) {  // feeds have finished loading
            $('.feedloading').fadeOut('fast');
        }
    } else if (this.worker === "initialization") { // status bar render for worker initialization
        var status = loadingStatus.index;
        var total = loadingStatus.totalItemsToLoad;
        var part = (100 / total);
        var currentPart = part * status;
        var newPart = part + currentPart;
        var newPartShow = Math.round(newPart);
        $('.progress > span').css('width', newPart + '%');
        $('.progress > span > span').text(newPartShow + '%');

        if (status + 1 === total) {
            $('.progress > span').css('width', '100%');
            $('.progress > span > span').text('100%');
            $('.progress').fadeOut('slow');
            $('#matchescount').fadeOut('slow');
        }
        $('#mainheader #matchescount #current-matchescount').html(loadingStatus.index + 1); // loading counter "X"/y
    } else { // any worker
    }
    loadingStatus.index = (++loadingStatus.index); // update loading status when append are done. (TO MOVE IN PROPER METHOD)
    if (loadingStatus.totalItemsToLoad === (loadingStatus.globalMonitor.error + loadingStatus.globalMonitor.success)) { // getMatchInfos loop is over

        if (loadingStatus.globalMonitor.error > 0) {
            $('#mainheader #matchescount #error-matchesload').append(loadingStatus.globalMonitor.error + this.errors.match.RetrieveFailedMatches);
            _log('********* WHOLE WORKER HAS FINISHED WITH ' + loadingStatus.globalMonitor.error + ' ERROR(S) *********');

            var dfd = new jQuery.Deferred();
            return dfd.resolve(this);
        }

        if (loadingStatus.globalMonitor.error === 0) { // Whole process has been complete without any error.
            _log('********* WHOLE WORKER HAS FINISHED WITHOUT ERRORS *********');

            var dfd = new jQuery.Deferred();
            return dfd.resolve(this);
        }
    } else { // One match has been forgotten in process
        _log('********* TRACKING, total:' + loadingStatus.totalItemsToLoad + ', success:' + loadingStatus.globalMonitor.success + ', error:' + loadingStatus.globalMonitor.error + ', *********');
        var dfd = new jQuery.Deferred();
        return dfd.resolve(this);
    }

};

/* *********** Feed Jobs *********** */

globalClass.prototype.appendEachFeed = function (worker, job, url, id, container, data) {
    _log('*** appendEachFeed ***');
    var self = this;
//    var data = JSON.parse(data.response);
    var data = data.datas.feedProperties;

    $.each(data, function (index, value) {
        var feedUrl = typeof value.feedUrls !== "undefined" ? value.feedUrls.reddit : value.feedUrl;
        container.append('<li><a href="' + feedUrl + '" target="_blank" title="' + value.feedCup + '">' + value.feedMatchname + ' - ' + value.feedDate + '</li>');
    });

    var dfd = new jQuery.Deferred();
    return dfd.resolve(this, this[this.worker].loadingStatus);

};

/* *********** Update Page *********** */

globalClass.prototype.getMainPageDistant = function () {
    _l('*** Initialization of Update Page Data  ***');
//    globalData.currentData = globalClass.initialization.data;    // store local infos retrieved with initialization worker
    console.log("getMainPageDistant", "this", this, this.worker);
    var dfd = new jQuery.Deferred();
    return dfd.resolve(this);
};

globalClass.prototype.parseMainPageDistant = function (worker, job, url, id, container, data) {
    _l('*** parse Main Page Data  ***');
    var self = this;
    console.log("Request received for worker:", worker, " job: ", job, " url: ", url, " id: ", id, " container: ", container, " RESULT DATA: ");
    var data = data.response;
    console.log('parseMainPageDistant', data)

    var dfd = new jQuery.Deferred();
    return dfd.resolve("", data);

};

globalClass.prototype.compareData = function () {
    _l('*** Compare Page Data ***');
    _l(this.worker)
    _l(this[this.worker])
    //COMPARE
    _l(globalData)

//    console.log('currentData', globalData.currentData)
//    console.log('newData', this[this.worker].data)

    var currentData = globalData.currentData;

//    var currentData = localStorage.getItem("currentData");
//    var currentData = JSON.parse(currentData);
//    console.log(currentData)
    var newData = this[this.worker].data;

//    console.log(JSON.stringify(currentData))
//    console.log(JSON.stringify(newData))

    var diffData = []; // result of currentData and newData comparison (add&rem) => will use it to compare current props (diffData[]) with new props (newData[])

    currentData.forEach(function (obj) { // cloning diffData with currentData
        diffData.push(obj);
    });

    function dataDifferenceADD(currentData, newData) {
        var x = {}

        currentData.forEach(function (obj) {
            x[obj.matchId] = obj;
        });


        return newData.filter(function (obj) {
            return !(obj.matchId in x);
        });
    }
    function dataDifferenceREM(currentData, newData) {
        var x = {}

        newData.forEach(function (obj) {
            x[obj.matchId] = obj;
        });


        return currentData.filter(function (obj) {
            return !(obj.matchId in x);
        });
    }
    var toAdd = dataDifferenceADD(currentData, newData);
    console.log('add', toAdd);
    var toRem = dataDifferenceREM(currentData, newData);
    console.log('rem', toRem);

// add and rem match(es) in currentData & dom

// add & rem to currentData obj:

    toAdd.forEach(function (obj) { //add
        diffData.push(obj); // push toAdd to diffData OBJ
    });


    toRem.forEach(function (obj) { //rem
        var index = diffData.map(function (x) {
            return x.matchId;
        }).indexOf(obj.matchId); // grep index of toRem matchId in currentData
        if (index > -1) {
            diffData.splice(index, 1); // remove toRem element(s) in diffData
        }
    });
    console.log("diffData", diffData)

    var propsToUpdate = [];

    for (var i = 0; i < diffData.length; i++) {
        var currentArray = diffData[i];
        // GET MATCHID
        var matchId = currentArray.matchId;
        // Grep matchId in newData
        var newArray = $.grep(newData, function (element, index) { // grep function array for current worker.
            return element.matchId === matchId;
        });
        var newArray = newArray[0];

        // compare current array values with new array values
        // get arrays props - return an array of props
        var currentArrayProps = Object.getOwnPropertyNames(currentArray);
        var newArrayProps = Object.getOwnPropertyNames(newArray);

        var percStatus = {}; // percentage UP, DOWN, ERR status
        for (var j = 0; j < currentArrayProps.length; j++) { // iterate over the props array
            var currentArrayProp = currentArray[currentArrayProps[j]];
            var newArrayProp = newArray[newArrayProps[j]];
            if ((currentArrayProp !== newArrayProp) && (typeof currentArrayProp !== 'object')) { // if values are different and el is not an obj, do.
                /* Results */
                // currentObj / newArray = [{"matchUrl":"http..", "matchId":"2767"..}]
                // prop / newArrayProps[j] = teamBReward 
                // newValue / newArrayProp = 5.4 for 1
                /* !Results */

                var currentObj = newArray;
                var currentValue = currentArrayProp;
                var newValue = newArrayProp;
                var prop = newArrayProps[j];

                console.log(newArrayProp, ' noteq in ', currentArrayProps[j], ' prop');
                console.log('currentObj', currentObj);
                console.log('currentValue', currentValue)
                console.log('newValue', newValue)
                console.log('prop', prop);

                if (prop === "teamBperc" || prop === "teamAperc") { // calculate if percentage goes UP or down
                    // access: propsToUpdate[index].percStatus.teamAperc
                    if (currentValue < newValue) {
                        percStatus[prop] = 'up'
                    }
                    else if (currentValue > newValue) {
                        percStatus[prop] = 'down'
                    }
                    else if (currentValue == newValue) {
                        percStatus[prop] = 'equal'
                    }
                    else {
                        percStatus[prop] = 'err'
                    }
                }
                var elementPos = propsToUpdate.map(function (x) {
                    return x.matchId;
                }).indexOf(newArray.matchId); // id in array


                if (elementPos > -1) { // obj for this matchId is already in propsToUpdate array
                    var obj = propsToUpdate[elementPos]; // obj
                    obj[prop] = newValue;
                    if (typeof percStatus[prop] !== "undefined" && percStatus[prop].length > 0) {
                        obj.percStatus = percStatus;
                    }
                }
                else { // obj not appearing in array, building it.
                    console.log("obj not appearing in array")
                    var objToPush = {
                        "matchId": newArray.matchId
                    }
                    objToPush[prop] = newValue;
                    if (typeof percStatus[prop] !== "undefined" && percStatus[prop].length > 0) {
                        objToPush.percStatus = percStatus;
                    }
                    propsToUpdate.push(objToPush);

                }
            }
        } // !for loop
    } // !for loop
    console.log('propsToUpdate', propsToUpdate)
    globalData.currentData = diffData; // update globalData Object
    this.propsToUpdate = propsToUpdate; // public prop, will be used by updateData to generate the VIEW
//    console.log(JSON.stringify(propsToUpdate))

    var dfd = new jQuery.Deferred();
    return dfd.resolve(this);
};
globalClass.prototype.updateData = function () {
    _l('*** Update Page Data  ***');
    console.log('*** Update Page Data  ***', this.propsToUpdate);
    // UPDATE
    /* 1) grep matchId
     * 2) find container in dom
     * 3) find props containers in matchmain container
     * 4) update containers
     */
//    var propsToUpdate = [{"matchId": "2904", "peopleItemsNum": "\n                20026 people placed 57614 items.\n                                "}, {"matchId": "2907", "teamBReward": "1.3 for 1", "valueBetB": "1.3 for 1", "peopleItemsNum": "\n                15373 people placed 44126 items.\n                                "}, {"matchId": "2905", "teamAReward": "3.24 for 1", "valueBetA": "3.24 for 1", "peopleItemsNum": "\n                11275 people placed 31350 items.\n                                "}, {"matchId": "2908", "teamBReward": "3.54 for 1", "valueBetB": "3.54 for 1", "peopleItemsNum": "\n                1279 people placed 3564 items.\n                                "}, {"matchId": "2911", "teamBReward": "3.71 for 1", "valueBetB": "3.71 for 1", "peopleItemsNum": "\n                722 people placed 1842 items.\n                                "}, {"matchId": "2910", "peopleItemsNum": "\n                894 people placed 2420 items.\n                                "}, {"matchId": "2909", "teamAReward": "1.91 for 1", "valueBetA": "1.91 for 1", "peopleItemsNum": "\n                567 people placed 1472 items.\n                                "}]
//    console.log(propsToUpdate.length)
    var propsToUpdate = this.propsToUpdate;

    function getPropValue(obj, prop) {
        var toRet;
        $.each(obj, function (propl, val) {
            if (propl === prop) {
                console.log(val)
                toRet = val;
                return false;
            }
        });
        return toRet;
    }

    for (var x in propsToUpdate) { // loop through propsToUpdate
        var obj = propsToUpdate[x]; // obj in propsToUpdate array
        var matchId = obj.matchId;
        var subContainer = $('body').find('a[href="match?m=' + matchId + '"]').closest('.match'); // .match ctn
        var container = subContainer.parent(); // .matchmain ctn
        console.log(container);

        for (var prop in obj) { // browse each prop of the obj

            if (prop !== "matchId" || prop !== "teamBperc" || prop !== "teamAperc") {
                var destCtnSel = getPropValue(this.propsContainers, prop) // where to append the prop
                var destCtn = container.find(destCtnSel);

                if (destCtn.length > 0) {
                    console.log('prop', prop, 'dest', destCtn, 'destSel', destCtnSel);
                    var newValue = obj[prop];
                    destCtn.html(newValue).delay(100).fadeOut().fadeIn('slow');
                }
            }
            if (prop === "teamBperc" || prop === "teamAperc") {
                console.log('/// percentage \\\/');
                var destCtnSel = getPropValue(this.propsContainers, prop) // where to append the prop
                var destCtn = container.find(destCtnSel);

                if (destCtn.length > 0) {
                    console.log('prop', prop, 'dest', destCtn, 'destSel', destCtnSel);
                    var newValue = obj[prop];
                    destCtn.html(newValue).delay(100).fadeOut().fadeIn('slow');
                }
                // arrows
                if(typeof obj.percStatus.teamAperc !== "undefined") {
                    var destCtnSel = getPropValue(this.propsContainers, prop) // where to append the prop
                    var destCtn = container.find(destCtnSel);
                }
                console.log('percentage', obj.percStatus.teamAperc);
                console.log('percentage', this.propsContainers.matchNameA);
                
                //var arrowCtnA = this.propsContainers.matchNameA;
                //var arrowCtnB = this.propsContainers.matchNameB;

                //.append(arrow).delay(100).fadeOut().fadeIn('slow');
            }

        }
    }



    var dfd = new jQuery.Deferred();
    return dfd.resolve(this);

};
globalClass.prototype.autoUpdateTimers = function () {
    var today = new Date();
    var hh = today.getHours();
    var mm = today.getMinutes();
    var ss = today.getSeconds();
    if (ss <= 9)
        ss = "0" + ss;
    if (mm === 0)
        mm = "0" + mm;
    var timeNow = hh + ':' + mm + ':' + ss;
    $('.au-lasttime').html(timeNow);

//    var mins = settings.updateDelay;
    var secs = settings.updateDelay / 1000;
    var currentSeconds = 0;
    var currentMinutes = 0;

    var autoUpdateTimer = setInterval(function () {
        auCountDown()
    }, 1000);

    function auCountDown() {
        currentMinutes = Math.floor(secs / 60);
        currentSeconds = secs % 60;
        if (currentSeconds <= 9)
            currentSeconds = "0" + currentSeconds;
        secs--;
        $('.au-timeleft').html(currentMinutes + "m " + currentSeconds + "s")
        if (secs === -1) {
            clearInterval(autoUpdateTimer);
            $('.au-timeleft').html('-');
        }
    }


}
/* *********** join Matches And Feed *********** */
globalClass.prototype.compareMatchesWithFeed = function () {
    _log('*** Compare Matches With Feeds ***');
};
globalClass.prototype.appendFeedToMatches = function () {
    _log('*** Append Feed to Matches ***');
};

function CompleteInitialization(worker, selector) {
//    var initGlobal = new globalClass('initialization'); // wrap init + get each match infos + appends
    var selector = (typeof selector === "undefined") ? "" : selector;
//    console.log(this)
    $.when(this.parseMainPage(selector)).then(function (that) {
        pLog('DONE:', 'parseMainPage', that);
        return that.globalInfos();
    }).then(function (that) {
        pLog('DONE:', 'globalInfos', that);
        return that.initLoading();
    }).then(function (that) {    // Get Match Infos LOOP
        var promisesCompleteInit = [];
        var data = that[that.worker].data;

        $.each(data, function (index, matchUrl) {
            var matchUrl = data[index].matchUrl;
            var matchId = data[index].matchId;
            var matchCtn = data[index].matchCtn;
            _log('curr =', matchUrl, that);

//    var p = aj();
//    promisesCompleteInit.push(p);
//    p.then(function(data){console.log('did', val)})
//    .then(function(data){console.log('@', index)});

            var p = that.ajaxCalls(that.worker, that.job, matchUrl, matchId, matchCtn, settings.defaultTimeout) //
            promisesCompleteInit.push(p);
//            $.when(that.ajaxCalls(that.worker, that.job, matchUrl, matchId, matchCtn, settings.defaultTimeout))
            p.done(function (data, textStatus, jqXHR) {
                var responseData = jqXHR.responseText;
                that.monitorWorker("success", matchCtn, matchId); // monitor global responses status to count how many succeed and failed.

                // when request is done, process the data.
                $.when(that.parseMatchPageData(that.worker, that.job, matchUrl, matchId, matchCtn, responseData)).then(function (that, data) {
                    return that.appendEachMatch(that.worker, that.job, matchUrl, matchId, matchCtn, data);
                }).then(function (that) {
                    pLog('DONE:', 'appendEachMatch', that);
                    return that.updateLoading(that[that.worker].loadingStatus);
                })

            })
            p.fail(function (jqXHR, stringStatus, exceptionObj) { // exceptionObj: "abort", "timeout", "No Transport".
                var globalMonitor = that[that.worker].loadingStatus.globalMonitor;
                if (exceptionObj) {
                    switch (exceptionObj) {
                        case 'abort':
                            var error = 'abort';
                            matchCtn.append(that.errors.match.aborted);
                            $('#mainheader #matchescount #error-matchesload').html(globalMonitor.error + that.errors.match.RetrieveFailedMatches);
                            matchCtn.find('.matchloading-ctn').remove();
                            that.monitorWorker("error", matchCtn, matchId); // monitor global responses status to count how many succeed and failed.
                            break;
                        case 'timeout':
                            var error = 'timeout';
                            matchCtn.append(that.errors.match.timedOut);
                            $('#mainheader #matchescount #error-matchesload').html(globalMonitor.error + that.errors.match.RetrieveFailedMatches);
                            matchCtn.find('.matchloading-ctn').remove();
                            that.monitorWorker("error", matchCtn, matchId); // monitor global responses status to count how many succeed and failed.
                            break;
                        case 'No Transport':
                            var error = 'No Transport';
                            matchCtn.append(that.errors.match.error);
                            $('#mainheader #matchescount #error-matchesload').html(globalMonitor.error + that.errors.match.RetrieveFailedMatches);
                            matchCtn.find('.matchloading-ctn').remove();
                            that.monitorWorker("error", matchCtn, matchId); // monitor global responses status to count how many succeed and failed.
                            break;
                    }
                } else {
                    var error = 'error';
                    console.log('errrrr', globalMonitor)
                    matchCtn.append(that.errors.match.error);
                    $('#mainheader #matchescount #error-matchesload').html(globalMonitor.error + that.errors.match.RetrieveFailedMatches);
                    matchCtn.find('.matchloading-ctn').remove();
                    that.monitorWorker("error", matchCtn, matchId); // monitor global responses status to count how many succeed and failed.
                }
                console.log('aaa', error);
                console.log('FAILLL', matchUrl)
            })
        }); // each ended.

        $.when.apply($, promisesCompleteInit)
//            .then(function () {
//                console.log('finished with no errors')
//                }, function () {
//                    console.log('E R R O R')
//            })

                .always(function () {
                    that.done();
                    console.log('done');
                    console.log('Initializing Update in ' + settings.updateDelay / 1000 / 60 + ' minutes');
                    if (settings.switches.autoupdate === true) {
                        that.autoUpdateTimers();
                        setInterval(function () {
                            console.log('UpdateInitialization');
                            that.autoUpdateTimers();
                            UpdateInitialization();
                        }, settings.updateDelay);
                    }
                })
                .done(function () {
                    console.log('Fired all methods for worker init were done without errors.')
                })
                .fail(function () {
                    console.log('Fired all methods for worker init were done WITH ERRORS.')
                });

    })
}
/*
 * @CompleteInitialization()
 "parseMainPage",
 "globalInfos",
 "initLoading",
 "getMatchInfos", // WRAPPED THIS DIRECTLY IN CompleteInitialization function.
 "ajaxCalls",
 "parseMatchPageData",
 "appendEachMatch",
 "updateLoading"
 */

function UpdateInitialization() {   // (AU = Auto Update)
    pLog('UpdateInitialization fired !');
    var initUpdate = new globalClass('updatePage'); // init page view only
    $.when(initUpdate.getMainPageDistant())
            .then(function (that) {
                var AUmainpage = initUpdate.ajaxCalls(initUpdate.worker, "updatePage", baseUrl, "", "", settings.defaultTimeout)
                AUmainpage.done(function (data, textStatus, jqXHR) {
                    pLog('req ', baseUrl, ' done.');
                    $.when(that.parseMainPage("", data))

//                    return that.parseMainPage("", data);
                            /* ---------------- */
                            .then(function (that, data) {    // Get Match Infos LOOP
                                _log('parseMainPage DONE', that[that.worker])
                                var promisesCompleteInit = [];
                                var data = that[that.worker].data;

                                $.each(data, function (index, matchUrl) {
                                    var matchUrl = data[index].matchUrl;
                                    var matchId = data[index].matchId;
                                    var matchCtn = data[index].matchCtn;
                                    //console.log('curr =', matchUrl, that);

                                    var px = that.ajaxCalls(that.worker, that.job, matchUrl, matchId, matchCtn, settings.defaultTimeout) //
                                    promisesCompleteInit.push(px);
                                    px.done(function (data, textStatus, jqXHR) {
                                        var responseData = jqXHR.responseText;
                                        pLog('DONE', that.worker, that.job, matchUrl, matchId, matchCtn);
                                        // when request is done, process the data.
                                        return that.parseMatchPageData(that.worker, that.job, matchUrl, matchId, matchCtn, responseData)

                                    })
                                    px.fail(function (jqXHR, stringStatus, exceptionObj) { // exceptionObj: "abort", "timeout", "No Transport".
                                        if (exceptionObj) {
                                            switch (exceptionObj) {
                                                case 'abort':
                                                    var error = 'abort';
                                                    break;
                                                case 'timeout':
                                                    var error = 'timeout';
                                                    break;
                                                case 'No Transport':
                                                    var error = 'No Transport';
                                                    break;
                                            }
                                        } else {
                                            var error = 'error';
                                        }
                                        pLog('FAILLL', error, matchUrl)
                                    })
                                }); // each ended.

                                $.when.apply($, promisesCompleteInit)

                                        //            .then(function () {
                                        //                console.log('finished with no errors')
                                        //                }, function () {
                                        //                    console.log('E R R O R')
                                        //            })

                                        .always(function () {
                                            $.when(that.compareData())
                                                    .then(function (that) {
                                                        console.log('finished with no errors')
                                                        console.log('compareData DONE', that[that.worker]);
                                                        return that.updateData();
                                                    }, function () {
                                                        console.log('E R R O R')
                                                    })
//                                return that.compareData();

                                        })
                                        .done(function (that) {
                                            console.log('Fired all methods for worker UPDATEPAGE were done without errors.')
                                        })
                                        .fail(function (that) {
                                            console.log('Fired all methods for worker UPDATEPAGE were done WITH ERRORS.')
                                        });

                            })
                    /* ---------------- */
                })
                AUmainpage.fail(function (jqXHR, stringStatus, exceptionObj) { // exceptionObj: "abort", "timeout", "No Transport".
                    console.log('req fail')
                })
            })
}
/*
 * @UpdateInitialization()
 "getMainPageDistant", // Ask ajax req to get the DISTANT main page
 "ajaxCalls", // req mainpage
 "parseMainPage", // parse ajax response using the matchesCtn built above
 "getMatchInfos", // LOOP -   Fire match pages requests
 "ajaxCalls", // LOOP -   
 "parseMatchPageData", // LOOP -   
 "updateLoading"    // LOOP -   
 "compareData",
 "updateData"
 */

/*
 parseMainPage
 initLoading
 
 */
/*
 * 1) get local main page
 * 
 * 2) get distant main page
 *  - get distant match pages
 * 3) compare
 * 4) update
 */


function FeedsInitialization() {
    var initFeeds = new globalClass('feeds'); // Turn on feeds
    $.when(initFeeds.initGlobalProcess()).then(function (that) {
        pLog('DONE:', 'initGlobalProcess', that);
        return that.globalInfos();
    }).then(function (that) {
        pLog('DONE:', 'globalInfos', that);
        return that.initLoading();
    }).then(function (that) {
        pLog('DONE:', 'initLoading', that);
        that[that.worker] = that.feeds;

        // ask ajaxCalls to request each feeds
        $.each(that.feeds.data, function (index, feedName) {
            var url = that.feeds.feedsDatas[feedName].url;
            var feedContainer = $("#" + feedName + "feed .feedslinks-box ul");
            var job = feedName;
            _log('feedName', that.worker, that.job, url, feedName, feedContainer)
            $.when(that.ajaxCalls(that.worker, that.job, url, feedName, feedContainer, 30000))
                    .done(function (data, textStatus, jqXHR) {
                        var responseData = jqXHR.responseJSON;
                        _log('AJAX CALL DONE', data, textStatus, jqXHR);
                        // when request is done, process the data.
                        $.when(that.appendEachFeed(that.worker, that.job, url, feedName, feedContainer, responseData)).then(function (that, data) {
                            return that.updateLoading(that.worker, that.job, url, feedName, feedContainer, data);
                        })
                                .fail(function (jqXHR, stringStatus, exceptionObj) { // exceptionObj: "abort", "timeout", "No Transport".

                                    if (exceptionObj) {
                                        switch (exceptionObj) {
                                            case 'abort':
                                                var error = 'abort';
                                                break;
                                            case 'timeout':
                                                var error = 'timeout';
                                                break;
                                            case 'No Transport':
                                                break;
                                        }
                                    } else {
                                        var error = 'error';
                                    }
                                    pLog('FAILLL', error, matchUrl)
                                })

                    });
        })
    }).done(function (that) {
        pLog('DONE:', 'ajaxCalls', that);
        pLog('done all.');
        initFeeds.done();
    });
}
/*
 * @Feeds()
 "initGlobalProcess",
 "globalInfos",
 "initLoading",
 "getFeeds",
 "ajaxCalls",
 "appendEachFeed",
 "updateLoading"
 */

function initialization(initType) {
//    var initGlobal = new globalClass('basicInit'); // init page view only
    var worker = 'initialization'; // default
    switch (initType) {
        case "complete":
            var worker = 'initialization';
            break;
        case "basic":
            var worker = 'basicInit';
            break;
    }
    var initGlobal = new globalClass(worker); // init page view only
    $.when(initGlobal.initGlobalProcess()).then(function (that) {
        pLog('DONE:', 'initGlobalProcess', that);
        return that.initPageView();
    }).then(function (that) {
        pLog('DONE:', 'initPageView', that);
    }).done(function (that) {
        pLog('DONE:', 'BasicInitialization', that);
        if (initType === "basic") { // a basic Init has been requested, finishing.
            return initGlobal.done();
        } else {    // a complete init has been requested, continueing.
            CompleteInitialization.call(initGlobal);
        }
    });
}
/*
 * @BasicInitialization()
 "initGlobalProcess",
 "initPageView"
 */
settings.switches.completeinit ? initialization('complete') : initialization('basic');
if (settings.switches.feeds === true) {
    FeedsInitialization();
}

//UpdateInitialization();




//var initGlobal = new globalClass('basicInit'); // init page view only
//var initGlobal = new globalClass('UpdatePage'); // wrap init + get each match infos + appends

//var initGlobal = new globalClass('initialization'); // wrap init + get each match infos + appends
//initGlobal.initGlobalProcess();
//var initFeeds = new globalClass('feeds');
//initFeeds.initGlobalProcess();
//
//var initUpdatePage = new globalClass('UpdatePage'); // init updateData worker
//initUpdatePage.initGlobalProcess();
//