/*
    This file should be included before all other GBE js file libraries such as
    com.globalbettingexchange.gec.js
    com.globalbettingexchange.gac.js
    com.globalbettingexchange.ui.js
*/


if (com === null || typeof(com) != "object") { var com = {};}
if (com.globalbettingexchange === null || typeof(com.globalbettingexchange) != "object") { com.globalbettingexchange = {};}
if (com.globalbettingexchange.base === null || typeof(com.globalbettingexchange.base) != "object") { com.globalbettingexchange.base = {};}

// all the functions in the com.gbeFragment namespace will go in this block
com.globalbettingexchange.base = {
    Test: function (divId) {

    },
    GBEFormatter: function (state) {
        var currentState = state;
        this.formatCurrency = function (amt, decimals, showCommas) {
            return this.formatDecimal(amt, decimals, showCommas);
        }
        this.formatNumber = function (amt, decimals, showCommas) {
            var currencySymbol = '';
            var formattedAmount = com.globalbettingexchange.base.formatDecimal(amt, decimals, currencySymbol, showCommas);
            return String.format("<span class='{0}'>{1}</span>", (amt < 0) ? 'negative' : 'positive', formattedAmount);
        }
        this.formatDecimal = function (amt, decimals, showCommas) {
            var currencySymbol = currentState.ccSymbol;
            var formattedAmount = com.globalbettingexchange.base.formatDecimal(amt, decimals, currencySymbol, showCommas);
            return String.format("<span class='{0}'>{1}</span>", (amt < 0) ? 'negative' : 'positive', formattedAmount);
        }
    },
    OddsLadder: function (prices) {
        var tolerancePercent = 0.0001;
        this.priceArray = prices;
        this.hashPriceArray = [];
        this.hashRepresentationArray = [];
        this.hashArray = [{ p: 2, r: 4 }, { p: 2, r: 4 }, { p: 2, r: 4 }, { p: 2, r: 4}];
        this.getItem = function (i) {
            return this.priceArray[i];
        };
        this.reindex = function (newprices) {
            this.priceArray = newprices;
            this.hashPriceArray = [];
            this.hashRepresentationArray = [];
            for (var i = 0; i < this.priceArray.length; i++) {
                this.hashPriceArray[this.priceArray[i].price] = this.priceArray[i];
                this.hashRepresentationArray[this.priceArray[i].representation] = this.priceArray[i];
            }
        };

        this.band = function (decimalPrice, direction, showRelative, isMultiple, mustBand) //showRelative = > <
        {
            //if its exactly on price ladder return price from hash(indexed) table
            if (this.hashPriceArray[decimalPrice] != null) return this.hashPriceArray[decimalPrice];


            var isDecimal = (this.priceArray[0].representation == "1.01");

            if (isMultiple) {
                if (isDecimal) {
                    var multipleDecimal = com.globalbettingexchange.base.formatDecimal(decimalPrice, 2, '', false);
                    return { price: decimalPrice, representation: com.globalbettingexchange.base.removeTrailingZeros(multipleDecimal) + "" };
                }
                //else {
                //    var multipleDecimal = com.globalbettingexchange.base.formatDecimal(decimalPrice - 1, 2, '', false);
                //    return { price: decimalPrice, representation: com.globalbettingexchange.base.removeTrailingZeros(multipleDecimal) + "/1" };
                //}
            }
            if (mustBand == null) mustBand = false;
            if (isDecimal)
                showRelative = false;


            if (decimalPrice == 0) return { price: 0, representation: '' };
            if (direction == null) direction = 1;
            var high = this.priceArray.length - 1;
            var low = 0;
            var mid = 0;

            while (low <= high) {
                mid = parseInt((low + high) / 2);
                if ((decimalPrice <= (this.priceArray[mid].price * (1 + tolerancePercent))) && (decimalPrice >= (this.priceArray[mid].price * (1 - tolerancePercent))) && (direction != -2) && (direction != 2)) {
                    return this.priceArray[mid];
                } else
                    if (this.priceArray[mid].price > decimalPrice) {
                        high = mid - 1;
                    }
                    else if (this.priceArray[mid].price < decimalPrice) {
                        low = mid + 1;
                    }
                    else {
                        return this.priceArray[mid];
                    }
            }

            if (!mustBand && isDecimal) {
                var offLadderDecimal = com.globalbettingexchange.base.formatDecimal(decimalPrice, 2, '', false);
                return { price: decimalPrice, representation: com.globalbettingexchange.base.removeTrailingZeros(offLadderDecimal) + "" };
            }

            if ((direction == -2) || (direction == 2)) {//only if not stepping(function below) using wheel or arrows, these would be +2 -2, 
                direction = direction / 2;
            }

            //not within tolerance of Best Found

            if (decimalPrice < this.priceArray[mid].price) {
                var index = Math.max(0, mid + (direction - 1) / 2); // -1 always show worst case for back;  change for lay
                if (showRelative)
                    return { price: this.priceArray[index].price, representation: '>' + this.priceArray[index].representation };
                else
                    return this.priceArray[index];
            }
            else {
                var index = Math.min(this.priceArray.length - 1, mid + (direction + 1) / 2);
                if (showRelative)
                    return { price: this.priceArray[index].price, representation: '>' + this.priceArray[index].representation };
                else
                    return this.priceArray[index];
            }
        };

        this.step = function (decimalPrice, direction) {
            decimalPrice = decimalPrice * (1 + (.00000001 * direction));
            direction = (direction) * 2;

            return this.band(decimalPrice, direction, false, false, true);
        };
        this.getFromRepresentation = function (representation) {
            return this.hashRepresentationArray[representation];
        };
        this.getFromDecimal = function (decimalValue) {
            if (this.hashPriceArray[decimalValue] != null)
                return this.hashPriceArray[decimalValue];
            else {
                return { price: 0, representation: "" };
            }
        };


    },
    Price: function (val) {
        function toString() {
            return com.globalbettingexchange.base.formatDecimal(val);
        }

    },
    MoneyAmount: function () {
        function toString() {
            return "ken";
        }
    },
    Format: function (str) {
        for (var i = 1; i < arguments.length; i++) {
            var itemToPlace = i - 1;
            str = str.replace('{' + itemToPlace + '}', arguments[i]);
        }
        return str;
    },
    formatDecimal: function (number, places, currencySymbol, showCommas) {

        var showZeros = (currencySymbol != null);
        if (currencySymbol == null) currencySymbol = '';
        if ((isNaN(number) || number == "") && (!showZeros)) {
            if (places == 0)
                return "";
            else
                return currencySymbol + "0.00";
        }

        //round to 2 decimal places
        number = Math.round(number * 100) / 100;

        //convert to string and add trailing zeroes if required
        var numberStr = (showCommas == true) ? this.addCommas(number.toString()) : number.toString();
        var decimalIndex = numberStr.indexOf(".");

        if (decimalIndex == -1) { numberStr += ".00"; }
        //only one decimal place, add trailing 0
        else if ((numberStr.length - 2) == decimalIndex) { numberStr += "0"; }

        if (currencySymbol != null) {
            // Insert currency symbol, after "-" if amount is negative
            if (numberStr.substring(0, 1) == "-")
                numberStr = "-" + currencySymbol + numberStr.substring(1);
            else
                numberStr = currencySymbol + numberStr;
        }
        if (places == 0)
            numberStr = numberStr.split('.')[0];
        return numberStr;
    },
    removeTrailingZeros: function (x) {
        var decPos = x.indexOf(".")
        if (decPos > -1) {
            first = x.substring(0, decPos);
            second = x.substring(decPos, x.length);
            while (second.charAt(second.length - 1) == "0")
                second = second.substring(0, second.length - 1);
            if (second.length > 1)
                return first + second;
            else
                return first;
        }
        return x;
    }, //end of removeTrailingZeros(x)
    validateInput: function (regex) {
        //int
        //decimal
        //string
        //
    },
    validatePrice: function () {

    },
    getFunctionName: function (funct) {
        var ownName = funct.toString();
        ownName = ownName.substr('function '.length);        // trim off "function "
        ownName = ownName.substr(0, ownName.indexOf('('));        // trim off everything after the function name
        return ownName;
    },
    addCommas: function (numberStr) {
        numberStr += '';
        x = numberStr.split('.');
        x1 = x[0];
        x2 = x.length > 1 ? '.' + x[1] : '';
        var rgx = /(\d+)(\d{3})/;
        while (rgx.test(x1)) {
            x1 = x1.replace(rgx, '$1' + ',' + '$2');
        }
        return x1 + x2;
    },
    /***********************
    preventBubble stops the click on price bubbling up to parent elements
    ************************/
    preventBubble: function (e) {
        if (!e) var e = window.event;
        e.cancelBubble = true;
        if (e.stopPropagation) e.stopPropagation();
    },
    getCurrencySymbol: function (code) {
        var currencySymbol = "&euro;";
        switch (code) {
            case 'AUD': currencySymbol = "$"; break;
            case 'CAD': currencySymbol = "$"; break;
            case 'CEU': currencySymbol = ""; break;
            case 'CNY': currencySymbol = "Y"; break;
            case 'EUR': currencySymbol = "&euro;"; break;
            case 'GBP': currencySymbol = "&pound;"; break;
            case 'HKD': currencySymbol = "$"; break;
            case 'INR': currencySymbol = "R"; break;
            case 'MYR': currencySymbol = ""; break;
            case 'PEU': currencySymbol = "&euro;"; break;
            case 'PGB': currencySymbol = "&pound;"; break;
            case 'PHP': currencySymbol = "P"; break;
            case 'PIN': currencySymbol = "R"; break;
            case 'PUS': currencySymbol = "$"; break;
            case 'RUB': currencySymbol = ""; break;
            case 'SGD': currencySymbol = "$"; break;
            case 'TWD': currencySymbol = ""; break;
            case 'UAH': currencySymbol = ""; break;
            case 'USD': currencySymbol = "$"; break;
        }
        return currencySymbol;
    },
    minimumStake: function () {
        return clientObject.minimumStakes[clientObject.state.currency];
    },
    getOverRound: function (marketObj, forExchange) {
        var forOverround = 0;
        var againstOverround = 0;
        for (selCount in marketObj.selections) {
            if (marketObj.selections[selCount].selectionStatusId == 2) {//Active

                if ((marketObj.selections[selCount].forExchangePrices[0] != null) && (forOverround != 9999))
                    forOverround += (1 / marketObj.selections[selCount].forExchangePrices[0].price);
                else { forOverround = 9999; }


                if ((marketObj.selections[selCount].againstExchangePrices[0] != null) && (againstOverround != 9999))
                    againstOverround += (1 / marketObj.selections[selCount].againstExchangePrices[0].price);
                else { againstOverround = 9999; }
                if ((againstOverround == 9999) && (forOverround == 9999))
                    break;
            }
        }

        forOverround = (forOverround == 9999) ? "" : this.formatDecimal(forOverround * 100, 2, '') + "%";
        againstOverround = (againstOverround == 9999) ? "" : this.formatDecimal(againstOverround * 100, 2, '') + "%";

        return { forOverround: forOverround, againstOverround: againstOverround };
    },
    dateToString: function (dateObj) {
        if (dateObj.indexOf != null) {
            dateObj = dateObj.replace('/', '');
            dateObj = dateObj.replace('/', '');
            dateObj = eval(dateObj);

        }
        var stringDate = dateObj.toString();
        return stringDate;
    },
    fixDate: function (dateObj) {
        if (dateObj != null) {
            if (dateObj.indexOf != null) {
                dateObj = dateObj.replace('/Date(', '');
                dateObj = dateObj.replace(')/', '');
                var dateObj1 = new Date();
                dateObj1.setTime(dateObj * 1);
                dateObj = dateObj1;

            }
        }
        return dateObj;
    },
    setCookie: function (c_name, value, expiredays) {
        var exdate = new Date();
        exdate.setDate(exdate.getDate() + expiredays);
        document.cookie = c_name + "=" + escape(value) +
        ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
    },
    getCookie: function (c_name) {
        if (document.cookie.length > 0) {
            c_start = document.cookie.indexOf(c_name + "=");
            if (c_start != -1) {
                c_start = c_start + c_name.length + 1;
                c_end = document.cookie.indexOf(";", c_start);
                if (c_end == -1) c_end = document.cookie.length;
                return unescape(document.cookie.substring(c_start, c_end));
            }
        }
        return "";
    },
    deleteCookie: function (name) {
        var exdate = new Date();
        exdate.setDate(exdate.getDate() - 1);
        document.cookie = c_name + "=" +
        ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
    },
    getFullYear: function (d) //returns the correct year for any year after 1000
    {
        var y = d.getYear();
        if (y < 1000) y += 1900;
        return y;
    },
    prefixZeros: function (num) {
        var numString = (num < 10) ? '0' + num : '' + num;
        return numString;
    },
    getEventName: function (fullName) {
        return fullName.substring(fullName.lastIndexOf('~') + 1);
    },
    getTopLevelEvent: function (ev) {
        if (ev.parent == null)
            return ev;
        else
            return this.getTopLevelEvent(ev.parent);

    },
    getEventLevel: function (ev) // gets the number of levels deep of event root is 0 , top level is 1
    {
        if (ev.parent == null)
            return 1;
        else
            return this.getEventLevel(ev.parent) + 1;

    },
    getRefreshRate: function (startTime, forLoggedInUser, forInRunningMarketOnly) {
        var currentTime = new Date();
        var rate = 100000;
        var diffMinutes = (startTime.getTime() - currentTime.getTime()) / 1000; //result in minutes

        var rateObject = { forLoggedInUser: false, from: 86400, to: 0, forInRunningMarketOnly: false, rate: 3600 };
        for (refreshI in clientObject.refreshRatesConfiguration.RefreshRates) {
            rateObject = clientObject.refreshRatesConfiguration.RefreshRates[refreshI];

            if (forInRunningMarketOnly && rateObject.forInRunningMarketOnly) {
                break;
            }

            if ((rateObject.forLoggedInUser == forLoggedInUser) && (rateObject.forInRunningMarketOnly == forInRunningMarketOnly)) {
                if ((rateObject.from <= diffMinutes) && (diffMinutes < rateObject.to)) {
                    break;
                }
            }
        }

        if (clientObject.refreshRatesConfiguration.RefreshRateLimits.enabled) {
            var numMarketsInView = clientObject.currentMarketsInView.length;
            var selectionsLimit = {};
            var marketsLimit = {};
            var numSelectionsInView = 0;

            for (rateI in clientObject.refreshRatesConfiguration.RefreshRateLimits.RefreshRates) {
                if ((clientObject.refreshRatesConfiguration.RefreshRateLimits.RefreshRates[rateI].numberOfMarkets > 0) && (clientObject.refreshRatesConfiguration.RefreshRateLimits.RefreshRates[rateI].enabled)) {
                    marketsLimit = clientObject.refreshRatesConfiguration.RefreshRateLimits.RefreshRates[rateI];
                    if ((numMarketsInView >= marketsLimit.numberOfMarkets) && (marketsLimit.rate > rateObject.rate))
                        return marketsLimit.rate * 1000;
                }

                if ((clientObject.refreshRatesConfiguration.RefreshRateLimits.RefreshRates[rateI].numberOfSelections > 0) && (clientObject.refreshRatesConfiguration.RefreshRateLimits.RefreshRates[rateI].enabled)) {
                    selectionsLimit = clientObject.refreshRatesConfiguration.RefreshRateLimits.RefreshRates[rateI];
                    for (marketI in clientObject.currentMarketsInView) {
                        numSelectionsInView += clientObject.currentMarketsInView[marketI].selections.length;
                    }
                    if ((numSelectionsInView >= selectionsLimit.numberOfSelections) && (selectionsLimit.rate > rateObject.rate))
                        return selectionsLimit.rate * 1000;
                }
            }

        }

        return rateObject.rate * 1000;
    },
    calcPnLs: function (markets, orders) {
        if (orders == null)
            orders = [];
        var marketTotals = []; //Array to hold total PL for each market
        var selectionTotals = []; //Array to hold total PL for each selection
        var marketTotals1 = []; //Indexed Array to hold total PL for each market
        var selectionTotals1 = []; //Indexed Array to hold total PL for each selection

        for (var i = 0; i < orders.length; i++) {
            var o = orders[i];
            if (marketTotals1[o.marketId()] == null) {
                marketTotals1[o.marketId()] = {};
                marketTotals1[o.marketId()].allSelectionsLosePnL = 0;
            }

            if (selectionTotals1[o.selectionId()] == null) {
                selectionTotals1[o.selectionId()] = {};
                selectionTotals1[o.selectionId()].selectionPnL = 0;
                selectionTotals1[o.selectionId()].selectionPnL1 = 0;
                selectionTotals1[o.selectionId()].selectionPnL2 = 0;
            }

            if (orders[i].polarityId == 1) {
                marketTotals1[o.marketId()].allSelectionsLosePnL -= o.matchedStake;
                selectionTotals1[o.selectionId()].selectionPnL += (o.averageMatchedPrice) * o.matchedStake;
                selectionTotals1[o.selectionId()].selectionPnL1 += (o.averageMatchedPrice - 1) * o.matchedStake;
                selectionTotals1[o.selectionId()].selectionPnL2 -= o.matchedStake;
            } else {
                marketTotals1[o.marketId()].allSelectionsLosePnL += o.matchedStake;
                selectionTotals1[o.selectionId()].selectionPnL -= (o.averageMatchedPrice) * o.matchedStake;
                selectionTotals1[o.selectionId()].selectionPnL1 -= (o.averageMatchedPrice - 1) * o.matchedStake;
                selectionTotals1[o.selectionId()].selectionPnL2 += o.matchedStake;
            }
        }

        for (var marketCount in markets) {
            m = markets[marketCount];
            if (m.numberOfWinningSelections == 1) {
                // Market has only one winner 

                // For each selection in the market, calculate P&L
                for (var selection in m.selections) {
                    var s = m.selections[selection];

                    var marketPnL = (marketTotals1[m.marketId] == null) ? 0 : marketTotals1[m.marketId].allSelectionsLosePnL;
                    var selectionPnL = (selectionTotals1[s.selectionId] == null) ? 0 : selectionTotals1[s.selectionId].selectionPnL;

                    selectionTotals[s.selectionId] = {};
                    selectionTotals[s.selectionId].PnL1 = marketPnL + selectionPnL;
                    selectionTotals[s.selectionId].PnL2 = -999999;   // special value meaning there is no P&L figure
                    selectionTotals[s.selectionId].PnL3 = -999999;   // special value meaning there is no P&L figure
                }
            }
            else {
                // number of winners not equal to 1, therefore show 2 P&L figures

                // For each selection in the market, calculate P&L
                for (selectionCount in m.selections) {
                    var s = m.selections[selectionCount];

                    var marketPnL = (marketTotals1[m.marketId] == null) ? 0 : marketTotals1[m.marketId].allSelectionsLosePnL;
                    var selectionPnL1 = (selectionTotals1[s.selectionId] == null) ? 0 : selectionTotals1[s.selectionId].selectionPnL1;
                    var selectionPnL2 = (selectionTotals1[s.selectionId] == null) ? 0 : selectionTotals1[s.selectionId].selectionPnL2;

                    /*var selectionPnL1 = 0;
                    var selectionPnL2 = 0;

                    // Find live bets on this selection
                    for (orderCount in orders) {
                    var o = orders[orderCount];
                    if (o.selectionId() == s.selectionId) {
                    //var matchedStake = o.matchedStake - o.unmatchedStake;
                    if (o.polarityId == 1) {
                    selectionPnL1 += (o.averageMatchedPrice - 1) * o.matchedStake;
                    selectionPnL2 -= o.matchedStake;
                    }
                    else {
                    selectionPnL1 -= (o.averageMatchedPrice - 1) * o.matchedStake;
                    selectionPnL2 += o.matchedStake;
                    }
                    }
                    }*/

                    selectionTotals[s.selectionId] = {};
                    selectionTotals[s.selectionId].PnL1 = selectionPnL1;
                    selectionTotals[s.selectionId].PnL2 = selectionPnL2;
                    selectionTotals[s.selectionId].PnL3 = -999999;  // special value meaning there is no P&L figure
                }
            }
        }
        return selectionTotals;
    },
    getTopDomain: function () {
        document.domain = document.domain; // remove :port numbers
        var domain = document.domain;
        var domainParts = domain.split('.');
        var topDomain = '';
        i = i;
        var partCount = 0;
        for (var i = domainParts.length - 1; i >= 0; i--) {
            partCount++;
            topDomain = domainParts[i] + '.' + topDomain;
            if (partCount == 2) break;
        }

        return topDomain.substring(0, topDomain.length - 1);
    },
    orderStatusName: function (id) {
        var returnVal;
        switch (id) {
            case 1: returnVal = "Active"; break; //Active
            case 2: returnVal = "Matched"; break;
            case 3: returnVal = "Expired"; break;
            case 4: returnVal = "Settled"; break;
            case 5: returnVal = "Void"; break;
            case 6: returnVal = "Suspended"; break;

            default: returnVal = "Unknown"; break;
        }
        return returnVal;
    },
    log: function (text) {
        return;
        if (window['console'] !== undefined) {
            console.log(text);
        }
        else {
            window.status = text;
        }
    }
}
//String.prototype.Format=com.globalbettingexchange.base.Format;

String.format = function(frmt,args)
{   
    for(var x=0; x<arguments.length; x++) {
        //var regex = "{" + x + "}";
        //var re = new RegExp(regex, "g");
        frmt = frmt.replace("{" + x + "}", arguments[x + 1]);
        frmt = frmt.replace("{" + x + "}", arguments[x + 1]);
    }
    return frmt;
}
String.repeat = function(chr,count)
{    
    var str = ""; 
    for(var x=0;x<count;x++) {str += chr}; 
    return str;
}
String.prototype.padL = function(width,pad)
{
    if (!width ||width<1)
        return this;   
 
    if (!pad) pad=" ";        
    var length = width - this.length
    if (length < 1) return this.substr(0,width);
 
    return (String.repeat(pad,length) + this).substr(0,width);    
}    
String.prototype.padR = function(width,pad)
{
    if (!width || width<1)
        return this;        
 
    if (!pad) pad=" ";
    var length = width - this.length
    if (length < 1) this.substr(0,width);
 
    return (this + String.repeat(pad,length)).substr(0,width);
} 
Date.prototype.formatDate = function(format)
{
    var date = this;
    if (!format)
      format="MM/dd/yyyy";               
 
    var month = date.getMonth() + 1;
    var year = date.getFullYear();    
 
    format = format.replace("MM",month.toString().padL(2,"0"));        
 
    if (format.indexOf("yyyy") > -1)
        format = format.replace("yyyy",year.toString());
    else if (format.indexOf("yy") > -1)
        format = format.replace("yy",year.toString().substr(2,2));
 
    format = format.replace("dd",date.getDate().toString().padL(2,"0"));
 
    var hours = date.getHours();//date.getUTCHours();       
    if (format.indexOf("t") > -1)
    {
       if (hours > 11)
        format = format.replace("t","pm")
       else
        format = format.replace("t","am")
    }
    if (format.indexOf("HH") > -1)
        format = format.replace("HH",hours.toString().padL(2,"0"));
    if (format.indexOf("hh") > -1) {
        if (hours > 12) hours - 12;
        if (hours == 0) hours = 12;
        format = format.replace("hh",hours.toString().padL(2,"0"));        
    }
    if (format.indexOf("mm") > -1)
       format = format.replace("mm",date.getMinutes().toString().padL(2,"0"));
    if (format.indexOf("ss") > -1)
        format = format.replace("ss", date.getSeconds().toString().padL(2, "0"));
    if (format.indexOf("SSS") > -1)
        format = format.replace("SSS", date.getMilliseconds().toString().padL(3, "0"));
    return format;
}

var InterfaceTypes = {"Exchange" : 1, "Sportsbook" : 2, "Pool" : 3, "Tote" : 4};
var ModeTypes = {"Singles" : 1, "Multiples" : 2};
var PriceFormatTypes = {"Decimal" : 1, "Fractional" : 2, "American" : 3 };
var WalletTypes = {"SinglePurse" : 1, "FundsTransfer" : 2};
var PunterTypes = {"GIS" : 1, "Native" : 2};


