(function($) {
    $(document).ready(function() {
        var dayMs = 1000 * 60 * 60 * 24;
        var hourMs = 1000 * 60 * 60;
        var minuteMs = 1000 * 60;

        $('.tipcg_countdown').each(function() {
            var $container = $(this);
            var type = ($container.data('type') || 'evergreen').toString().toLowerCase();
            var template = ($container.data('template') || 'default').toString().toLowerCase();
            var intervalId = null;
            var completed = false;

            function showContainer() {
                $container.css('display', '').removeClass('tipcg-is-pending');
            }

            function complete() {
                if (completed) {
                    return;
                }

                completed = true;
                render(0);

                if (intervalId) {
                    clearInterval(intervalId);
                }

                showContainer();
            }

            function formatUnit(value) {
                return value < 10 ? '0' + value : value.toString();
            }

            function setAdaptiveCardWidth($unit, formatted) {
                var $value = $unit.find('.tipcg-clock-front, .value').first();
                var fontSize = parseFloat($value.css('font-size')) || 40;
                var length = Math.max(2, formatted.toString().length);
                var width = Math.ceil((length * fontSize * 0.68) + (fontSize * 0.45));

                $unit.css('--tipcg-adaptive-card-width', width + 'px');
            }

            function setUnitValue(unitClass, value) {
                var formatted = formatUnit(value);
                var $unit = $container.find('.' + unitClass);

                if (template === 'flip_clock') {
                    setAdaptiveCardWidth($unit, formatted);

                    var $clockCard = $unit.find('.tipcg-clock-card');
                    var $clockFront = $unit.find('.tipcg-clock-front');
                    var $clockBack = $unit.find('.tipcg-clock-back');
                    var clockCommitted = $unit.data('tipcg-value');
                    var clockPending = $unit.data('tipcg-clock-pending');

                    function commitClockValue(number) {
                        $clockFront.text(number);
                        $clockBack.text(number);
                        $clockCard.removeClass('is-flipping');
                        $unit.data('tipcg-value', number);
                        $unit.removeData('tipcg-clock-pending');
                        $unit.removeData('tipcg-clock-timer');
                    }

                    if (typeof clockCommitted === 'undefined') {
                        commitClockValue(formatted);
                        return;
                    }

                    if (clockPending === formatted) {
                        return;
                    }

                    if (typeof clockPending !== 'undefined') {
                        window.clearTimeout($unit.data('tipcg-clock-timer'));
                        commitClockValue(clockPending);
                        clockCommitted = clockPending;
                    }

                    if (clockCommitted !== formatted) {
                        $clockBack.text(formatted);
                        $clockCard.removeClass('is-flipping');

                        if ($clockCard.length) {
                            $clockCard[0].offsetWidth;
                        }

                        $clockCard.addClass('is-flipping');
                        $unit.data('tipcg-clock-pending', formatted);
                        $unit.data('tipcg-clock-timer', window.setTimeout(function() {
                            commitClockValue(formatted);
                        }, 620));
                    }

                    return;
                }

                $unit.find('.value').text(formatted);
            }

            function render(distanceMs) {
                var remaining = distanceMs;
                if (remaining < 0) {
                    remaining = 0;
                }

                var days = Math.floor(remaining / dayMs);
                var hours = Math.floor((remaining % dayMs) / hourMs);
                var minutes = Math.floor((remaining % hourMs) / minuteMs);
                var seconds = Math.floor((remaining % minuteMs) / 1000);
                var hideDays = days === 0;

                $container.toggleClass('tipcg-days-hidden', hideDays);
                $container.find('.tipcg-separator-days-hours').toggle(!hideDays);

                if (hideDays) {
                    $container.find('.days').hide();
                } else {
                    $container.find('.days').show();
                    setUnitValue('days', days);
                }

                setUnitValue('hours', hours);
                setUnitValue('minutes', minutes);
                setUnitValue('seconds', seconds);
            }

            function runEvergreen() {
                var startTime = parseInt($container.data('start-time'), 10) * 1000;
                var duration = parseInt($container.data('duration'), 10) * 1000;

                if (isNaN(startTime) || isNaN(duration)) {
                    return;
                }

                var endTimestamp = startTime + duration;

                function tick() {
                    var distance = endTimestamp - Date.now();

                    if (distance < 0) {
                        complete();
                        return;
                    }

                    render(distance);
                    showContainer();
                }

                intervalId = setInterval(tick, 1000);
                tick();
            }

            function runFixed() {
                var target = parseInt($container.data('target-time'), 10) * 1000;

                if (isNaN(target) || target <= 0) {
                    return;
                }

                function tick() {
                    var distance = target - Date.now();

                    if (distance < 0) {
                        complete();
                        return;
                    }

                    render(distance);
                    showContainer();
                }

                intervalId = setInterval(tick, 1000);
                tick();
            }

            if (type === 'fixed') {
                runFixed();
            } else {
                runEvergreen();
            }
        });
    });
})(jQuery);
