(function () {
    'use strict';

    function ready(fn) {
        if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', fn, { once: true });
        else fn();
    }

    function getJSON(url) {
        return fetch(url, {
            credentials: 'same-origin',
            headers: { 'Accept': 'application/json' },
            cache: 'no-store'
        }).then(function (response) {
            if (!response.ok) throw new Error('HTTP ' + response.status);
            return response.json();
        });
    }

    var csTime = {
        csDays: 0,
        csHours: 0,
        csMinutes: 0,
        csSeconds: 0,
        csTimeLeft: 0,
        csNextStageTimeLeft: 0,
        battleMode: false,
        timer: null,
        init: function () {
            var self = this;
            getJSON(baseUrl + 'api/castlesiege.php').then(function (data) {
                self.csTimeLeft = Number(data.TimeLeft) || 0;
                self.csNextStageTimeLeft = Number(data.NextStageTimeLeft) || 0;
                self.expiresAt = Date.now() + (self.csTimeLeft * 1000);
                self.nextStageAt = Date.now() + (self.csNextStageTimeLeft * 1000);
                self.update();
                self.timer = window.setInterval(function () {
                    if (!document.hidden) self.update();
                }, 1000);
            }).catch(function () {});
        },
        update: function () {
            if (isFinite(this.expiresAt)) this.csTimeLeft = Math.max(0, Math.ceil((this.expiresAt - Date.now()) / 1000));
            if (isFinite(this.nextStageAt)) this.csNextStageTimeLeft = Math.max(0, Math.ceil((this.nextStageAt - Date.now()) / 1000));

            if (this.csTimeLeft >= 1) {
                var daysModule = this.csTimeLeft % 86400;
                this.csDays = (this.csTimeLeft - daysModule) / 86400;
                var hoursModule = daysModule % 3600;
                this.csHours = (daysModule - hoursModule) / 3600;
                var minutesModule = hoursModule % 60;
                this.csMinutes = (hoursModule - minutesModule) / 60;
                this.csSeconds = minutesModule;
                this.battleMode = false;
            } else {
                this.battleMode = true;
                this.csDays = this.csHours = this.csMinutes = this.csSeconds = 0;
            }

            var targets = [document.getElementById('cscountdown'), document.getElementById('siegeTimer')].filter(Boolean);
            if (!targets.length) return;
            if (this.battleMode) {
                targets.forEach(function (el) { el.textContent = 'Battle'; });
                return;
            }

            var countdown = '';
            if (this.csTimeLeft > 86400) countdown += this.csDays + '<span>d</span> ';
            if (this.csTimeLeft > 3600) countdown += this.csHours + '<span>h</span> ';
            if (this.csTimeLeft > 60) countdown += this.csMinutes + '<span>m</span> ';
            countdown += this.csSeconds + '<span>s</span>';
            targets.forEach(function (el) { el.innerHTML = countdown; });
        }
    };

    var serverTime = {
        weekDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
        monthNames: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
        dateOffset: 0,
        ids: null,
        timer: null,
        init: function (serverId, localId, serverDateId, localDateId, serverEpoch, serverOffset) {
            var self = this;
            this.ids = { server: serverId, local: localId, serverDate: serverDateId, localDate: localDateId };
            var epoch = Number(serverEpoch);
            var offset = Number(serverOffset);
            if (isFinite(epoch) && epoch > 0 && isFinite(offset)) {
                this.serverBaseMs = (epoch + offset) * 1000;
                this.clientBaseMs = Date.now();
                this.update(true);
                this.timer = window.setInterval(function () {
                    if (!document.hidden) self.update(false);
                }, 1000);
                return;
            }
            getJSON(baseUrl + 'api/servertime.php').then(function (data) {
                var serverDate = new Date(data.ServerTime);
                var localDate = new Date();
                if (isNaN(serverDate.getTime())) return;
                self.dateOffset = serverDate.getTime() - localDate.getTime();
                self.update(true);
                self.timer = window.setInterval(function () {
                    if (!document.hidden) self.update(false);
                }, 1000);
            }).catch(function () {});
        },
        update: function (updateDates) {
            if (!this.ids) return;
            var local = new Date();
            var embeddedClock = isFinite(this.serverBaseMs) && isFinite(this.clientBaseMs);
            var server = embeddedClock ? new Date(this.serverBaseMs + (Date.now() - this.clientBaseMs)) : new Date(local.getTime() + this.dateOffset);
            var elLocal = document.getElementById(this.ids.local);
            var elServer = document.getElementById(this.ids.server);
            if (elLocal) elLocal.textContent = this.dateTimeFormat(local, false);
            if (elServer) elServer.textContent = this.dateTimeFormat(server, embeddedClock);
            if (updateDates) {
                var localDateEl = document.getElementById(this.ids.localDate);
                var serverDateEl = document.getElementById(this.ids.serverDate);
                if (localDateEl) localDateEl.textContent = this.dateFormat(local, false);
                if (serverDateEl) serverDateEl.textContent = this.dateFormat(server, embeddedClock);
            }
        },
        dateTimeFormat: function (date, utc) {
            var hours = utc ? date.getUTCHours() : date.getHours();
            var minutes = utc ? date.getUTCMinutes() : date.getMinutes();
            var seconds = utc ? date.getUTCSeconds() : date.getSeconds();
            return this.digit(hours) + ':' + this.digit(minutes) + ':' + this.digit(seconds);
        },
        dateFormat: function (date, utc) {
            var day = utc ? date.getUTCDay() : date.getDay();
            var month = utc ? date.getUTCMonth() : date.getMonth();
            var dateNum = utc ? date.getUTCDate() : date.getDate();
            return this.weekDays[day] + ' ' + this.monthNames[month] + ' ' + dateNum;
        },
        digit: function (value) {
            value = String(value);
            return value.length === 1 ? '0' + value : value;
        }
    };

    function rankingRows() {
        return Array.prototype.slice.call(document.querySelectorAll('.rankings-table tr[data-class-id]'));
    }

    function rankingsFilterByClass() {
        var allowed = Array.prototype.slice.call(arguments).map(function (value) { return parseInt(value, 10); }).filter(function (value) { return !isNaN(value); });
        rankingRows().forEach(function (row) {
            var classId = parseInt(row.getAttribute('data-class-id'), 10);
            row.hidden = allowed.indexOf(classId) === -1;
        });
    }

    function rankingsFilterRemove() {
        rankingRows().forEach(function (row) { row.hidden = false; });
    }

    window.csTime = csTime;
    window.serverTime = serverTime;
    window.rankingsFilterByClass = rankingsFilterByClass;
    window.rankingsFilterRemove = rankingsFilterRemove;

    ready(function () {
        if (document.getElementById('tServerTime') && document.getElementById('tLocalTime') && document.getElementById('tServerDate') && document.getElementById('tLocalDate')) {
            var clock = document.querySelector('.nex-times[data-server-epoch]');
            serverTime.init('tServerTime', 'tLocalTime', 'tServerDate', 'tLocalDate', clock ? clock.getAttribute('data-server-epoch') : '', clock ? clock.getAttribute('data-server-offset') : '');
        }

        if (document.getElementById('cscountdown') || document.getElementById('siegeTimer')) csTime.init();

        var conversion = document.getElementById('paypal_conversion_rate_value');
        var amount = document.getElementById('amount');
        var result = document.getElementById('result');
        if (conversion && amount && result) {
            var rate = parseInt(conversion.textContent, 10) || 0;
            amount.addEventListener('input', function () {
                if (!/^\d*$/.test(amount.value)) amount.value = amount.value.replace(/\D+/g, '');
                var value = parseInt(amount.value, 10);
                result.textContent = isNaN(value) ? '0' : String(rate * value);
            });
        }

        document.querySelectorAll('a.rankings-class-filter-selection').forEach(function (link) {
            link.addEventListener('click', function () {
                document.querySelectorAll('a.rankings-class-filter-selection').forEach(function (item) {
                    item.classList.add('rankings-class-filter-grayscale');
                });
                link.classList.remove('rankings-class-filter-grayscale');
            });
        });

        var select = document.getElementById('rankings-class-filter-select');
        if (select) {
            select.addEventListener('change', function () {
                var value = select.value;
                if (!value) {
                    rankingsFilterRemove();
                    return;
                }
                var ids = value.split(',').map(function (part) { return parseInt(part.trim(), 10); }).filter(function (id) { return !isNaN(id); });
                rankingsFilterByClass.apply(null, ids);
            });
        }
    });
}());
