/*
Copyright 2012-2025 VeloViewer. All Rights Reserved
###V50###
*/
var us, s, a, ao, aoall = null,
    cs, o, segs = [],
    totalSegs = 0,
    stBatchSize = 50,
    segAsyncCount = 0,
    shAsyncCount = 0,
    errorShown = false,
    genderFilter = 'All';

function refreshData() {
    d3.select('#checkPlacingsWrapper').text('Updating leaderboards... 0 of ' + s.hunters.length);
    shAsyncCount = 0;
    s.hunters.forEach(function(d) {
        shAsyncCount++;
        $.ajax({
            url: '/api/getSegmentHunterS3New.php?id=' + d.id,
            async: true,
            success: function(result) {
                shAsyncCount--;
                d3.select('#checkPlacingsWrapper').text('Updating leaderboards... ' + (s.hunters.length - shAsyncCount) + ' of ' + s.hunters.length);
                var o = result;
                if (shAsyncCount == 0) {
                    document.location.reload();
                }
            }
        });
    });
}

function handleSegmentData(result) {
    result.standings = clone(result);
    delete result.segments;
    s.hunters.push(result);

    if (s.hunters.length == hunters.length) {
        var huntersObj = {};
        hunters.forEach(function(d) {
            huntersObj[d.id] = d.order;
        });
        s.hunters.sort(function(a, b) {
            return huntersObj[a.id] > 0 ? huntersObj[a.id] - huntersObj[b.id] : a.id - b.id
        });
        processData();
        displayData();
    }
}


function checkPlacings() {
    if (!isPRO) {
        alert('PRO users only');
        return;
    }
    if (myClubs.indexOf(s.hunters[0].clubId) == -1) {
        alert('Not in club');
        return;
    }
    /*if (typeof(ao[contextAthleteId]) !== 'undefined') {
        alert('Update in regional leaderboards only please.');
        return;
    }*/
    segAsyncCount = 0;
    var segsToCheck = arrayUnique(d3.merge(s.hunters.map(function(d) {
        return d.standings.segments
    })).map(function(d) {
        return d.id
    }));
    d3.select('#checkPlacingsWrapper').text('Checking... 0 of ' + segsToCheck.length);

    segsToCheck.forEach(function(d) {
        segAsyncCount++;
        $.ajax({
            url: '/api/getHunterSegmentEfforts.php?id=' + d,
            async: true,
            success: function(result) {
                segAsyncCount--;
                d3.select('#checkPlacingsWrapper').text('Checking... ' + (segsToCheck.length - segAsyncCount) + ' of ' + segsToCheck.length);
                if (segAsyncCount == 0) {
                    refreshData();
                    if (hasLocalStorage) {
                        localStorage.setItem('shslc' + s.hunterSeries, new Date().getTime());
                    }
                }
            },
            error: function(xhr, textStatus, errorThrown) {
                segAsyncCount--;
                d3.select('#checkPlacingsWrapper').text('Checking... ' + (segsToCheck.length - segAsyncCount) + ' of ' + segsToCheck.length);
                if (segAsyncCount == 0) {
                    refreshData();
                    if (hasLocalStorage) {
                        localStorage.setItem('shslc' + s.hunterSeries, new Date().getTime());
                    }
                }
                console.debug(xhr);
            }
        });
    })
}

function getSegments() {
    s = {
        hunterSeries: shsid
    };
    s.hunters = [];
    hunters.forEach(function(d) {
        $.ajax({
            url: 'https://s3.veloviewer.com/' + d.url,
            turl: d.url,
            async: true,
            contentType: "application/json",
            dataType: 'jsonp',
            error: function(xhr, textStatus, errorThrown) {
                if (textStatus != 'parsererror') {
                    $.ajax({
                        parentCall: this,
                        parentXhr: xhr,
                        async: true,
                        url: '/api/checkName.php?n=' + this.turl,
                        success: function(d) {
                            if (d.status == 'success') {
                                this.parentCall.url = 'https://s3.veloviewer.com/' + d.name;
                                $.ajax(this.parentCall);
                            } else {
                                if (!errorShown) {
                                    alert('Error getting data file, try refreshing the page.');
                                    errorShown = true;
                                }
                            }
                        }
                    });
                }
            }
        });
    });
}

function checkClubs() {
    $.ajax({
        url: '/api/checkClubs.php',
        async: true,
        success: function(result) {
            if (typeof(result.error) === 'undefined') {
                myClubs = result;
                if (result.indexOf(s.hunters[0].clubId) > -1) {
                    document.location.reload();
                } else {
                    alert('You still don\'t seem to be a member of the "' + s.hunters[0].clubName + '" Strava club.');
                }
            } else {
                alert('Unable to get clubs :-(');
            }
        },
        error: function(xhr, textStatus, errorThrown) {
            alert('Unable to get clubs :-(');
        }
    });
}

function processData() {
    ao = {};
    if (loggedInAthleteId > 0 && gender != '') {
        s.hunters.forEach(function(d) {
            if (d.athletes[loggedInAthleteId]) {
                d.athletes[loggedInAthleteId].g = gender;
            }
        });
    }
    if (!s_s) {
        s.hunters.forEach(function(c) {
            c.standings.segments.forEach(function(d) {
                d.result.entries.forEach(function(e) {
                    e.t = 0;
                });
            });
        });
    }
    s.hunters.forEach(function(c) {
        c.standings.segments.forEach(function(d){
            d.result.entries.sort(function(a,b){ return a.t == b.t ? +a.i - b.i : a.t - b.t })
        });
    });
    totalSegs = d3.sum(s.hunters, function(d) {
        return d.standings.segments.length
    });
    s.hunters.forEach(function(d) {
        d.standings.segments.forEach(function(e) {
            segs.push({
                'id': e.id,
                'name': e.name,
                'kom': e.kom,
                'qom': e.qom,
                'rating': e.rating
            });
            if (typeof(e.result) !== 'undefined') {
                if (genderFilter == 'All') {
                    e.result.entriesF = e.result.entries;
                } else {
                    e.result.entriesF = e.result.entries.filter(function(f) { return d.athletes[f.i].g == genderFilter || (genderFilter == 'M' && d.athletes[f.i].g == '') || (genderFilter == 'F' && d.athletes[f.i].g == 'G') });
                }
                e.result.entriesF.forEach(function(f, i) {
                    f.r = i > 0 && e.result.entries[i - 1].t == f.t ? e.result.entries[i - 1].r : i + 1;
                    if (typeof(ao[f.i]) === 'undefined') {
                        ao[f.i] = {
                            id: f.i,
                            name: d.athletes[f.i].n.replace(/\\/g, ''),
                            gender: d.athletes[f.i].g == '' ? 'M' : d.athletes[f.i].g,
                            hunters: {}
                        };
                    }
                    if (typeof(ao[f.i].hunters[d.id]) === 'undefined') {
                        ao[f.i].hunters[d.id] = {
                            id: d.id,
                            hunter: d,
                            segs: {}
                        };
                    }
                    if (typeof(ao[f.i].hunters[d.id].segs[e.id]) === 'undefined') {
                        ao[f.i].hunters[d.id].segs[e.id] = {
                            id: e.id,
                            segName: e.name,
                            rank: f.r,
                            isKom: s_s && (typeof(e.aid) === 'undefined' || e.aid == '') ? f.t <= (ao[f.i].gender == 'M' ? e.kom : e.qom) : false,
                            bonus: s_s ? (f.t <= (ao[f.i].gender == 'M' ? e.kom : e.qom) ? d.kqomBonus : 0) : 0,
                            placingScore: s_s ? (e.result.entriesF.length + 1 - f.r) * (100 / (e.result.entriesF.length + 1)) : 0
                        };
                    }
                });
            }
        });
    });
    if (aoall == null) {
        aoall = ao;
    }
    a = d3.values(ao);
    a.forEach(function(d) {
        d.hunters = d3.values(d.hunters);
        d.hunters.forEach(function(e) {
            e.segs = d3.values(e.segs);
            e.bonus = (e.segs.length >= e.hunter.segCountBonusFrom ? e.segs.length * e.hunter.segCountBonus : 0);
            e.segPlacingScore = d3.sum(e.segs, function(f) {
                return f.placingScore
            });
            e.segBonusScore = d3.sum(e.segs, function(f) {
                return f.bonus
            });
            e.totalScore = e.bonus + e.segPlacingScore + e.segBonusScore;
        });
        d.segPlacingScore = d3.sum(d.hunters, function(f) {
            return f.segPlacingScore
        });
        d.segBonusScore = d3.sum(d.hunters, function(f) {
            return f.segBonusScore + f.bonus
        });
        d.totalScore = d.segPlacingScore + d.segBonusScore;
        d.totalSegs = d3.sum(d.hunters, function(f) {
            return f.segs.length
        });
    });
    a.sort(function(a, b) {
        return b.totalScore - a.totalScore
    });

    a.forEach(function(d, i) {
        d.rank = i > 0 && a[i - 1].totalScore == d.totalScore ? a[i - 1].rank : i + 1
    });

    s.hunters.forEach(function(c) {
        var b = a.filter(function(d) {
                return d.hunters.map(function(e) {
                    return e.id
                }).indexOf(c.id) > -1
            })
            .sort(function(a, b) {
                return b.hunters.filter(function(d) {
                    return d.id == c.id
                })[0].totalScore - a.hunters.filter(function(d) {
                    return d.id == c.id
                })[0].totalScore
            });

        var lastScore = 10000000;
        var lastRank = 1;
        b.forEach(function(d, i) {
            var o = d.hunters.filter(function(e) {
                return e.id == c.id
            })[0];
            if (o.totalScore == lastScore) {
                o.rank = lastRank;
            } else {
                o.rank = i + 1;
                lastScore = o.totalScore;
                lastRank = i + 1;
            }
        });
    });

    var segCheckP = d3.select('.container-fluid > .row-fluid').selectAll('#checkPlacingsWrapper').data([0]);
    segCheckP.selectAll('button.remove, span').remove();
    segCheckP.enter().append('p').attr('id', 'checkPlacingsWrapper');
    segCheckP.style('clear', 'both');

    if (s.hunterSeries != 30) {
        segCheckP.append('span').classed('hidden-phone', true).html('Data from Apple, Wahoo, Garmin, Suunto, Coros, etc. devices.');
    }

    var genderRadio = segCheckP.selectAll('#genderRadio').data([0]).enter()
        .append('div').attr('id', 'genderRadio').style('float', 'right')
        .attr({
            'class': 'btn-group',
            'data-toggle': 'buttons-radio'
        }).each(function() {
            d3.select(this).selectAll('button').data(['All', 'M', 'F']).enter()
                .append('button').classed('btn btn-primary btn-mini', true).html(function(d) {
                    switch (d) {
                        case 'M':
                            return 'Male';
                        case 'F':
                            return 'Female';
                        case 'All':
                            return 'All';
                    }
                }).classed('active', function(d) { return d == 'All' });
        });

    genderRadio.selectAll('button').on('click', function(d) {
        genderFilter = d;
        processData();
        displayData();
    });

    if (contextAthleteId > 0) {
        if (false && isPRO) {
            if (myClubs.indexOf(s.hunters[0].clubId) > -1) {
                if ((new Date().getTime() - localStorage.getItem('shslc' + s.hunterSeries)) > 1000 * 60 * 60 * 24) {
                    segCheckP.append('button')
                        .on('click', checkPlacings)
                        .classed('btn btn-primary btn-small remove', true)
                        .text(typeof(aoall[contextAthleteId]) === 'undefined' ? 'Check your times' : 'Update your times');
                    if (typeof(aoall[contextAthleteId]) === 'undefined') {
                        segCheckP.append('span').style('margin-left', '5px').text('Checking your times implies you are happy for your name and data to be shown in these public leaderboards.');
                    } else {
                        segCheckP.append('span').style('margin-left', '5px').text('Please only update when you have completed a new segment or improved a time :-)');
                    }
                } else {
                    segCheckP.append('span').text('Your placings can only be rechecked in bulk once a day.');
                }
            } else {
                segCheckP.classed('alert alert-info', true).html('You must be a member of the "' + s.hunters[0].clubName.replace(' Insider', '') + '" Strava club to appear in this leaderboard. Please <a href="https://www.strava.com/clubs/' + s.hunters[0].clubId + '" target="_blank">join the club</a> and then <button class="btn btn-primary btn-small" id="checkClubMembershipBtn">recheck club membership</button>');
                d3.select('#checkClubMembershipBtn').on('click', function() {
                    checkClubs();
                });
            }
        } else {
            //segCheckP.append('span').classed('alert alert-info', true).html('Head to the individual leaderboards to update your times.');
        }
    }

    d3.selectAll('#dataTable tbody tr').remove();
    d3.selectAll('#dataTable colgroup').remove();
    d3.selectAll('#dataTable')
        .append('colgroup').each(function() {
            var cg = d3.select(this);
            cg.append('col')
                .style('width', 'auto');
            cg.append('col')
                .style('width', 100 / (s.hunters.length + 3) + '%');
            s.hunters.forEach(function(e) {
                cg.append('col')
                    .style('width', 'auto');
                cg.append('col')
                    .style('width', 'auto');
                cg.append('col')
                    .style('width', 100 / (s.hunters.length + 3) + '%');
            });
            cg.append('col')
                .style('width', 100 / (s.hunters.length + 3) + '%');
            cg.append('col')
                .style('width', 100 / (s.hunters.length + 3) + '%');
        });

    d3.selectAll('#dataTable thead tr *').remove();
    d3.select('#dataTable thead tr').each(function() {
        var tr = d3.select(this);
        tr.selectAll('th')
            .data(d3.merge([
                ['Rank', 'Name'], s.hunters, ['Completed', 'Points']
            ]))
            .enter()
            .append('th')
            .style('background', function(d) {
                return typeof(d.colour) === 'undefined' ? null : '#' + d.colour;
            })
            .classed('ar', function(d, i) {
                if (typeof(d) === 'string' && i > 1) {
                    return true;
                }
                return false;
            })
            .attr('colspan', function(d, i) {
                if (typeof(d) !== 'string') {
                    return 3;
                }
                return null;
            })
            .html(function(d) {
                if (typeof(d) !== 'string') {
                    return d.title.replace('-', '&#8209;').toUpperCase() + '<br/><a href="' + (typeof(d.alias) !== 'undefined' && d.alias != '' && d.alias != null ? '/' + d.seriesAlias + '/' + d.alias : '/segmentHunter/' + d.id) + '">View</a>'
                }
                return d
            });
    });

    if (s.hunters.length == 0) {
        d3.select('#title').html('None in series!');
    } else {
        d3.select('#title').html(clubName + (seriesName == '' ? '' : ' - ' + seriesName));
    }

    d3.select('#hunterDesc').html(seriesDesc)
        .classed('lead', false);

    initScrollingTable(d3.select('.tableWrapper'), function() {
        var availableHeight = parseInt(window.innerHeight) - this.getBoundingClientRect().top - 20 - pageYOffset;
        if (availableHeight > parseInt(d3.select(this).select('.st-body table').style('height'))) {
            return null;
        }
        return Math.max(280, availableHeight) + 'px';
    });
}

function getData() {
    var data = a;

    data = data.sort(function(a, b) {
        if (o == null) {
            return b.totalScore - a.totalScore;
        }
        switch (typeof(o.innerText) === 'undefined' ? o.textContent : o.innerText) {
            case 'Rank':
            case 'Overall Total':
                return b.totalScore - a.totalScore;
                break;
            case 'Bonus Total':
                return (b.bonusTotal == a.bonusTotal ? b.totalScore - a.totalScore : b.bonusTotal - a.bonusTotal);
                break;
            case 'Placing Total':
                return b.placingScore - a.placingScore;
                break;
            case 'Name':
                return (a.name < b.name ? -1 : 1);
                break;
            case '#':
                return (b.segs == a.segs ? b.totalScore - a.totalScore : b.segs - a.segs);
                break;
            default:
                return ((typeof(a['seg' + o.__data__.id]) !== 'undefined' ? a['seg' + o.__data__.id].rank : 10000) - (typeof(b['seg' + o.__data__.id]) !== 'undefined' ? b['seg' + o.__data__.id].rank : 10000))
                return 0;
        }
    });

    var ls = -1;
    var lsr = -1
    if (data[0] && typeof(data[0].rank) === 'undefined') {
        for (var i = 0; i < data.length; i++) {
            if (data[i].totalScore == ls) {
                data[i].rank = lsr;
            } else {
                data[i].rank = i + 1;
                ls = data[i].totalScore;
                lsr = i + 1;
            }
        }
    }

    return data;
}

function displayData() {
    var data = getData();
    var curAth = a.filter(function(d) {
        return d.id == contextAthleteId
    });
    data = data.slice(stBatchNumber * stBatchSize, stBatchSize);
    if (curAth.length > 0) {
        curAth = clone(curAth[0]);
        curAth.id = -curAth.id;
        data = d3.merge([
            [curAth],
            [{
                id: 0
            }], data
        ]);
    }
    d3.select('#dataTable tbody')
        .selectAll('tr')
        .data(data, function(d) {
            return d.id
        })
        .enter()
        .append('tr')
        .classed('info', function(d) {
            return Math.abs(d.id) == contextAthleteId
        })
        .each(function(d, i) {
            var tr = d3.select(this);
            tr.append('td')
                .html(d.id == 0 ? '&nbsp;' : suf(d.rank));
            tr.append('td')
                .attr('id', 'ath' + d.id)
                .style('max-width', '150px')
                //.html('<a href="http://app.strava.com/athletes/' + d.id + '" target="_blank"><img class="shProfileImg" src="' + (d.img == 'avatar/athlete/large.png' ? 'http://d26ifou2tyrp3u.cloudfront.net/assets/avatar/athlete/large-162a16b208e0364313ec8ce239ffd7a8.png' : d.img) + '">' + d.name + (d.gender == 'F' ? ' (F)' : '') + '</a>');
                .html(d.id == 0 ? '&nbsp;' : '<a href="http://www.strava.com/athletes/' + Math.abs(d.id) + '" target="_blank">' + d.name + (d.gender == 'F' ? ' (F)' : '') + '</a>');

            s.hunters.forEach(function(e) {
                var hi = d.id == 0 ? -1 : d.hunters.map(function(f) {
                    return f.hunter.id
                }).indexOf(e.id);
                if (hi > -1) {
                    var koms = d.hunters[hi].segs
                        .filter(function(f) {
                            return f.isKom
                        });

                    tr.append('td')
                        .attr('colspan', 3)
                        .html(suf(d.hunters[hi].rank) + ' ' + (koms.length <= 3 ? koms.map(function(f) { return '<img style="width:19px;height:13px" src="' + https + '://' + assetPrefix + '/img/kom.png">' }).join('') : '<img style="width:19px;height:13px" src="' + https + '://' + assetPrefix + '/img/kom.png"> x' + koms.length) + (-1 * d.id == +contextAthleteId ? '<br/>' + d.hunters[hi].segs.length + ' of ' + e.standings.segments.length : ''))
                        .attr('title', d.hunters[hi].segs.length + ' of ' + e.standings.segments.length + ' completed.');
                } else {
                    tr.append('td')
                        .attr('colspan', 3)
                        .html('&nbsp;');
                }
            })
            tr.append('td')
                .classed('ar', true)
                .html(d.id == 0 ? '&nbsp;' : d.totalSegs + ' / ' + totalSegs);
            tr.append('td')
                .classed('ar', true)
                .html(d.id == 0 ? '&nbsp;' : fInt(d.totalScore));
        });

    d3.selectAll('#dataTable tbody td')
        .style('background-color', function(d) {
            return d.totalSegs == totalSegs ? 'rgba(213, 163, 23,0.5)' : null;
        });

    d3.select('#dataInfo').html('Showing ' + Math.min(a.length, stBatchSize) + ' of ' + a.length);

    if (stBatchSize < a.length) {
        d3.selectAll('#loadNext50Btn, #loadAllBtn').style('display', null);
    } else {
        d3.selectAll('#loadNext50Btn, #loadAllBtn').style('display', 'none');
    }

    setScrollingTableSize();
}

d3.select('#tableFooter')
    .style('margin-top', '4px')
    .append('button')
    .attr('id', 'loadNext50Btn')
    .style('display', 'none')
    .classed('btn btn-primary', true)
    .text('Show next 50 rows')
    .on('click', function() {
        stBatchSize += 50;
        displayData();
    });

d3.select('#tableFooter')
    .append('button')
    .attr('id', 'loadAllBtn')
    .style('display', 'none')
    .classed('btn btn-primary', true)
    .text('Show all')
    .on('click', function() {
        stBatchSize = a.length;
        displayData();
    });

d3.select('#tableFooter')
    .append('span')
    .style('margin-left', '20px')
    .attr('id', 'dataInfo');

getSegments();

if (!s_s) {
    d3.select(d3.select('#hunterDesc').node().parentElement).insert('p', 'p').attr('id', 'summitLimits').classed('alert alert-info', true)
        .html('<b>Important note:</b> Segment times and placings are <a href="' + s_sBlogLink + '" target="_blank">only available to Strava Subscribers</a>. VeloViewer users can get a <a href="https://promo.strava.com/veloviewer/" target="_blank">60 day free Strava Premium trial here</a>.');
}

var infoUl = d3.select('#infoPanel');
infoUl.append('li').html('Full info on how these leaderboards work please see <a target="_blank" href="https://blog.veloviewer.com/updated-100-climbs-segment-hunter-strava-leaderboards/">this blog post</a>.');
infoUl.append('li').html('Clicking on an athlete\'s name will take you to their Strava profile.');
infoUl.append('li').append('div').attr('id', 'deleteSegmentHunterEffortsWrapper').append('button')
    .classed('btn btn-primary', true)
    .on('click', function() {
        if (confirm('Are you sure you want to delete your data from all of these club-based leaderboards?')) {
            d3.select('#deleteSegmentHunterEffortsWrapper').html('Deleting...');
            $.ajax({
                url: '/api/deleteSegmentHunterEfforts.php',
                async: true,
                success: function(result) {
                    if (typeof(result.error) === 'undefined') {
                        alert('All your data has been deleted from these leaderboards (although may remain in the cache for a couple of hours).');
                        d3.select('#deleteSegmentHunterEffortsWrapper').html('All your data has been deleted from these leaderboards (although may remain in the cache for a couple of hours).');
                        refreshData();
                    } else {
                        alert('Unable to delete data :-(');
                    }
                },
                error: function(xhr, textStatus, errorThrown) {
                    d3.select('#deleteSegmentHunterEffortsWrapper').html('Error deleting :-(');
                    alert('Unable to delete data :-(');
                }
            });
        }
    })
    .html('Delete all of your data from these leaderboards');

if (contextAthleteId <= 0) {
    d3.select(d3.select('#hunterDesc').node().parentElement)
        .insert('div', ':first-child').style({
            'margin-left': '-4px',
            'margin-top': '-7px'
        }).html('<a href="https://www.strava.com/oauth/authorize?client_id=36&scope=read,read_all,profile:read_all,profile:write,activity:read,activity:read_all,activity:write&redirect_uri=' + document.location.href + '&response_type=code&approval_prompt=auto&state=private"><img style="height:40px" src="https://cf.veloviewer.com/img/btn_strava_connectwith_orange.svg"></a> <div style="display: inline-block;vertical-align: middle;">to view your own position</div>')
}
