﻿// Global toast config
var toast = new Toasty({ progressBar: true });
toast.transition('slideLeftRightFade');

$(function () {
    // My Learning Center link setup
    $(document).on('click', 'a[href*="3feb89af-b6d8-43d0-bb65-cc22fecc1adf"]', function (e) {
        e.preventDefault();

        const self = this;
        $.post('/getauthcode', function (data) {
            if (data === "/account/logout") {
                window.location.href = "/account/logout";
                return;
            }
            else if (data !== '') {
                const code = data.split('|');
                let url = self.href.replace("3feb89af-b6d8-43d0-bb65-cc22fecc1adf", code[0]);
                url += '&personid=' + code[1];
                window.open(url, "_blank");
            }
        });
    });

    // https://web.dev/bfcache/
    // Back/forward cache automatically loads cached versions of webpages to speed up quick back and forth navigation.
    // These pages are loaded in their last state so if a loader was showing it would always be showing, hiding the content.
    // This turns off loaders when pages load from bfCache
    $(window).on('pageshow', function () {
        $('body').removeClass('busy');
    });

    if (window.location.hostname.toLowerCase().indexOf('dev') != -1)
        $('#site-header .upper-nav').addClass('dev-mode');

    // DotDotDot configuration

    // Currently affects only _ListItem items
    $(document).on('click', '.cc-list-item .ddd-ellipsis > a.read-more', function (e) {
        e.preventDefault();
        e.stopPropagation();

        const $this = $(e.target);
        const shouldScroll = !$this.hasClass('d-block');
        const $scrollTo = $this.closest('.cc-list-item').children('.scroll-to');

        $this.removeClass('d-block'); // block elements mess with this plugin, so have to remove it before init
        toggleRead($this[0]);

        if (shouldScroll && $scrollTo?.length > 0) {
            $([document.documentElement, document.body]).animate({
                scrollTop: $scrollTo.offset().top - 165
            }, 300);
        }
    });

    // Currently affects only _CourseBody bundle items
    $(document).on('click', '.gradient-card-wrapper .ddd-ellipsis > a.read-more', function (e) {
        e.preventDefault();
        e.stopPropagation();

        const $this = $(e.target);
        const shouldScroll = !$this.hasClass('d-block');
        const $scrollTo = $this.closest('.gradient-card-wrapper').children('.scroll-to');

        $this.removeClass('d-block'); // block elements mess with this plugin, so have to remove it before init
        toggleRead($this[0]);

        const $container = $("#course-main-tab-content");
        if (shouldScroll && $scrollTo?.length > 0) {
            $($container).animate({
                scrollTop: $scrollTo.offset().top - $container.offset().top + $container.scrollTop() - 50
            }, 300);
        }
    });

    const options = {
        height: 96,
        tolerance: 5, // matches padding-top of .read-more
        keep: 'a.read-more',
        ellipsis: "\u2026",
    };

    $.initialize('.ddd-ellipsis', function () {
        const $collapse = $(this);
        const $richText = $('.rich-text', $collapse);
        const text = $.trim($richText.text());
        const needsReadMore = $richText.height() > 96; // 96px is four lines of text (24px line-height * 4)

        if (text && needsReadMore) {
            // append Read More toggler
            $collapse.append('<a href="javascript:void(0);" class="read-more">Read More</a>');
            // Init truncate plugin
            const dot = new Dotdotdot(this, options);
            $collapse.data('dot-api', dot);
        }
    });

    // Search setup
    $('.upper-nav #btnSearch').on('click', function () {
        $('.search-drawer').toggleClass('open');
        if ($('.search-drawer').hasClass('open'))
            $('.search-drawer input').focus();
    });

    $(window).scroll(function () {
        var scrollingUp = (this.oldScroll > this.scrollY);

        if (!scrollingUp && $('.search-drawer').hasClass('open')) {
            $('.search-drawer').removeClass('open');
        }

        this.oldScroll = this.scrollY;
    });

    $('.search-drawer input').on('keypress', function (e) {
        if (e.keyCode === 13)
            $('.search-drawer button').trigger('click');
    });

    $('.search-drawer button').on('click', function (e) {
        e.preventDefault();

        window.location = '/search?indexCatalogue=a&searchQuery=' + encodeURIComponent($('.search-drawer input').val().trim());
    });

    // Setup up mobile menu
    if ($('#mobile-nav').length && !$('.sfPageEditor').length) { // don't init mmenu in Sitefinity page editor

        var searchContainerMobile = $('.search-form-container-mobile', '#site-header').clone(true, true);
        $('.search-form-container-mobile', '#site-header').remove();

        const mmenu = new Mmenu('#mobile-nav', {
            // options
            navbar: {
                title: ' '
            },
            //navbars: [
            //    {
            //        'position': 'top',
            //        'content': [
            //            searchContainerMobile.html()
            //        ]
            //    },
            //    {
            //        'position': 'bottom',
            //        'content': [
            //            '<a class="fa fa-facebook" href="#" target="_blank"></a>',
            //            '<a class="fa fa-twitter" href="#" target="_blank"></a>',
            //            '<a class="fa fa-linkedin" href="#" target="_blank"></a>',
            //            '<a class="fa fa-instagram" href="#" target="_blank"></a>'
            //        ]
            //    }
            //],
            extensions: ['position-right']
        }, {
            // configuration
            offCanvas: {
                page: {
                    selector: '#pageNode'
                }
            },
            classNames: {
                fixedElements: {
                    fixed: "mmenu-fixed"
                }
            }
        });

        $('.mobile-search-container').html(searchContainerMobile.html());

        $('.mobile-search-container input').on('keypress', function (e) {
            if (e.keyCode === 13)
                $('.mobile-search-container button').trigger('click');
        });

        $('.mobile-search-container button').on('click', function (e) {
            e.preventDefault();

            window.location = '/search?indexCatalogue=a&searchQuery=' + encodeURIComponent($('.mobile-search-container input').val().trim());
        });

        const mmenu_api = mmenu.API;

        mmenu_api.bind('open:start', function () {
            $('#site-header .hamburger').addClass('active');
        });

        mmenu_api.bind('close:start', function () {
            $('#site-header .hamburger').removeClass('active');
        });

        $('.hamburger').on('click', function (e) {
            e.preventDefault();

            if ($(this).hasClass('active'))
                mmenu_api.close();
            else
                mmenu_api.open();
        });

        //featherSearchBoxWidget(serverSearchDataMobile);
    }

    // Datepickers
    $.initialize('input.datepicker', function () {
        const minDate = $(this).data('min-date');
        const minDateObj = minDate != null
            ? { minDate: minDate }
            : {};

        new Datepicker(this, minDateObj);
    });

    // init tooltips (works with dynamically added tooltips and the santize false is to allow more complex html markup for the tooltip)
    $('body').tooltip({ selector: '[data-toggle=tooltip]', sanitize: false });

    $('[data-valmsg-for]').prev('.form-control').on('change', function () {
        if ($(this).hasClass('valid')) $(this).closest('form-group').removeClass('has-error');
    });

    // Input masks
    $('.phone-input').each(function () {
        IMask(this, {
            mask: '(000) 000-0000'
        });
    });

    $('.currency-input').each(function () {
        IMask(this, {
            mask: Number,
            scale: 2,
            padFractionalZeros: true,
            radix: '.',
            min: 0
        });
    });

    // Gradient nav
    $.initialize('.gradient-nav a[data-toggle="tab"]', function () {
        const baseHeight = 40;
        const openHeight = ($('.gradient-nav .nav-link').length * baseHeight) + 5;

        $(this).on('click', function (e) {
            if ($(window).width() < 768) {
                e.preventDefault();

                var $nav = $(this).closest('nav.nav'),
                    isOpen = $nav.hasClass('open');

                $nav.toggleClass('open');
                $nav.css('height', isOpen ? baseHeight : openHeight);
            }
        });
    });
    $(window).on('resize', function () {
        if ($(window).width() > 767)
            $('.gradient-nav').removeClass('open').removeAttr('style');
    });

    //$(window).scroll(function () {
    //    var scrollingUp = (this.oldScroll > this.scrollY);

    //    if ($(this).scrollTop() > 20 && !scrollingUp) {
    //    if ($(this).scrollTop() > 20) {
    //        $('#site-header').addClass('fixed');
    //    } else {
    //        $('#site-header').removeClass('fixed');
    //    }

    //    this.oldScroll = this.scrollY;
    //});

    //if ($(window).scrollTop() > 20)
    //    $('#site-header').addClass('fixed');

    // below is used to fix scroll overflow issues when a "grid-12" layout template is used on a page with being nested in a container
    $.initialize('.row[data-sf-element]', function () {
        var $row = $(this),
            $parent = $row.parent();

        if (!($parent.hasClass('container') || $parent.hasClass('container-fluid')))
            $row.addClass('containerless');
    });

    const params = new Proxy(new URLSearchParams(window.location.search), {
        get: (searchParams, prop) => searchParams.get(prop),
    });

    if (params.errorMsg) toast.error(params.errorMsg);

    $.initialize('[data-topic-color]', function () {
        let $topic = $(this);
        const topicColor = $topic.data('topic-color');
        // TODO: Original design colors commented out here. Jason requested we use another set of colors 9/1/2023
        // const background = chroma.valid(topicColor) ? topicColor : "59316F"; // default to purple
        const background = chroma.valid(topicColor) ? topicColor : "562759"; // default to purple
        const foreground = getForegroundColor(background);

        $topic.css({ "background-color": "#" + background, "color": foreground });
    });

    $.initialize('[data-gradient-colors]', function () {
        try {
            let $item = $(this);
            let colors = $item.attr('data-gradient-colors')?.split(',')?.filter(x => x != null && x != "" && chroma.valid(x))?.map(x => '#' + x);
            // TODO: Original design colors commented out here. Jason requested we use another set of colors 9/1/2023
            // if (colors.length <= 0) colors.push('#59316F');
            if (colors.length <= 0) colors.push('#562759');
            if (colors.length === 1) {
                const secondColor = getMonochromeLighter(colors[0]);
                colors.push(secondColor);
            }

            const background = getBackgroundGradient(colors);
            $item.css("background", background);
        } catch (error) {
            //console.log('Error: ', error);
        }
    });

    $.initialize('#paymentMethodsTab.active .payment-expired', function () {
        toast.warning("One of your saved payment methods is expired!");
    });

    $(document).on('click', '[data-course-detail]', async function () {
        $(this).addClass("loading");
        const detail = await getSitefinityUrls('CatalogDetail');
        const id = $(this).data('course-detail');
        window.location.href = `${detail}/${id}`;

        removeLoaders();
    });

    $(document).on('click', '[data-default-payment]', function () {
        const $self = $(this);
        const id = $self.data('default-payment');
        const { origin } = window.location;

        // get in case setting fails so we can restore.
        const currentDefault = getCurrentDefaultPaymentMethodId();
        handleStyleDefaultPaymentMethod(id);

        $.post(`${origin}/setdefaultpayment`, { id: id }, function (d) {
            if (d.Success) {
                toast.success("Default payment method saved!");
            } else {
                handleStyleDefaultPaymentMethod(currentDefault);

                toast.error(`There was a problem setting this payment method as default. Please try again.`)
            }
        });
    });

    const getCurrentDefaultPaymentMethodId = () => {
        const $input = $('.payment-method-card.selected [data-default-payment]:checked');
        return $input?.data('default-payment');
    };

    const handleStyleDefaultPaymentMethod = (id) => {
        $('.payment-method-card').removeClass('selected');
        $('.pmc-select').removeClass('pmc-select-default-payment checked');
        $('.pmc-select input').removeAttr('checked');

        const $newDefault = $(`[data-default-payment="${id}"]`);
        $newDefault.attr('checked', true);
        $newDefault.closest('.pmc-select').addClass('pmc-select-default-payment checked');
        $newDefault.closest('.payment-method-card').addClass('selected');
    };

    $(document).on('click', '[data-delete-payment]', function () {
        const id = $(this).data('delete-payment');
        const { origin } = window.location;
        const confirmed = confirm("Are you sure you want to delete this payment method?");
        if (confirmed) {
            $.post(`${origin}/deletepaymentmethod`, { id: id }, function (d) {
                if (d.Success) {
                    $(`[data-delete-payment="${id}"]`).closest('.payment-method-card').remove();

                    toast.success("Payment method deleted!");
                } else {
                    toast.error(`There was a problem deleting this payment method. Please try again.`)
                }
            });
        }
    });

    $(document).on('click', '[data-auto-renew-off]', function () {
        const id = $(this).data('auto-renew-off');
        const { origin } = window.location;
        const confirmed = confirm("Are you sure you want to turn off auto-renew for this subscription?");
        if (confirmed) {
            $.post(`${origin}/turnoffautorenew`, { id: id }, function (d) {
                if (d.Success) {
                    window.location.hash = "#subscriptions";
                    window.location.reload();
                } else {
                    toast.error(`There was a problem turning off auto-renew for this subscription. Please try again.`)
                }
            });
        }
    });

    $(document).on('click', '[data-membership-checkout]', function () {
        $('body').addClass('busy');

        $.post('/Membership/Registration/RedirectToCheckout', function (d) {
            $('body').removeClass("busy");
            const { CartUrl } = d || {}
            window.location.href = CartUrl || "/checkout";
        });
    });

    $(document).on('submit', 'form.license-form', function (e) {
        e.preventDefault();

        var $form = $(this);

        var licenses = [];
        $('.license-item-wrapper :input').each(function (i, item) {
            licenses.push(JSON.parse($(item).val()));
        });

        var $tabPane = $form.closest('.tab-pane');
        var t = setTimeout(function () { $tabPane.addClass('busy') }, 750);

        $.post($form[0].action, { licenses: licenses }, function (data) {
            if (t) clearTimeout(t);
            $tabPane.removeClass('busy');

            if (data.Success) toast.success('Licenses updated successfully!');
            else toast.error(data.Message ?? "Something went wrong. Please try again.");
        });
    });

    $(document).on('click', '.new-license-form button', function (e) {
        e.preventDefault();

        const $form = $(this).closest('.new-license-form');
        const vals = $(':input', $form).serializeArray();

        const name = vals.at(0);
        const state = vals.at(1)
        const cert = vals.at(2);
        const expiration = vals.at(3);
        const noExpiration = isNull(expiration?.value);

        let isValid = true;
        if ([name, state, cert].some(x => isNull(x?.value))) isValid = false;
        else if (noExpiration && state?.value == "OH") isValid = false;

        if (!isValid)
            toast.error('Please complete all fields.');
        else {
            const credentials = $('[data-credentials-lookup]').data('credentials-lookup');
            const nameDisplay = (credentials || []).find(x => x.ID == name?.value)?.Name;

            const data = {
                CertificateNumber: cert.value,
                ExpirationDate: noExpiration ? null : expiration.value,
                IsCPA: $(this).data('license-type') === 'cpa',
                AdditionalCredentialID: name.value,
                PersonAdditionalCredentialsID: "-1",
                State: state.value,
                NameDisplay: nameDisplay,
            };

            data.LicenseJson = JSON.stringify(data);

            var template = $('#license-template').html();
            $form.next().append(Mustache.render(template, data));

            $(':input', $form).val('');
            $('select', $form).val('-1');
        }
    });

    const isNull = (val) => val == null || val == '' || val == '-1' || val == '0';

    $(document).on('click', '.license-remove', function (e) {
        e.preventDefault();
        if (confirm('Remove license from list?'))
            $(this).closest('.license-item-wrapper').remove();
            handleDisableOhio();
    });

    $(document).on('click', '[data-license-type="Primary"]', function () {
        handleDisableOhio();
    });

    $('.new-license-form #LicenseState').on('change', function (e) {
        const { target: { value } } = e || {};
        $('.new-license-form #ExpirationDate').closest('.form-group').toggle(value === 'OH');
    });

    $(window).on('resize', function () {
        var $modal = $('#course-modal');
        if ($modal.length && $modal.hasClass('show'))
            setCourseModelTabContentSize($modal);
    });
});

function getBackgroundGradient(colors) {
    var result = "";

    let uniqueColors = [... new Set(colors)];
    const count = uniqueColors.length;
    const [firstColor, secondColor] = uniqueColors;

    const isMonochromatic = count === 2 && getMonochromeLighter(firstColor) === secondColor;
    if (!isMonochromatic) {
        // Desired order from design docs
        // TODO: Original design colors commented out here. Jason requested we use another set of colors 9/1/2023
        // const order = ['#974DBF', '#D636A6', '#DB4020', '#EB9F11', '#94E44E', '#3BBFAB', '#4391B4', '#196095', '#59316F'];
        const order = ['#E200CA', '#E1035F', '#BD2417', '#F15A24', '#CEE53E', '#28E53F', '#2BE59E', '#2DA0A0', '#2B5C4A', '#1956DF', '#562759'];
        uniqueColors.sort((a, b) => order.indexOf(a) - order.indexOf(b));
    }

    // Examples:
    // 2 colors - transparent linear-gradient(0deg,#59316f 0%,#974dbf 100%) 0% 0% no-repeat padding-box
    // 3 colors - transparent linear-gradient(0deg,#59316f 0%,#974dbf 50%, #fff 100%) 0% 0% no-repeat padding-box
    // 4 colors - transparent linear-gradient(0deg,#59316f 0%, #eee 33%, #ddd 66%, #fff 100%) 0% 0% no-repeat padding-box
    // 5 colors - transparent linear-gradient(0deg,#59316f 0%, #eee 25%, #ddd 50%, #ddd 75%, #fff 100%) 0% 0% no-repeat padding-box

    var percent = 0.0;
    var percentIncrement = Math.round(100.0 / (count - 1));

    for (var i = 0; i < count; i++) {
        const color = uniqueColors[i];

        if (i == 0)
            result += `transparent linear-gradient(0deg, ${color} ${percent}%,`;
        else if (i < count - 1)
            result += `${color} ${percent}%,`;
        else
            result += `${color} 100%) 0% 0% no-repeat padding-box`;

        percent += percentIncrement;
    }

    return result;
}

function getMonochromeLighter(color) {
    return chroma(color).desaturate(0).brighten(1.25).hex();
}

function getForegroundColor(hexcolor) {
    hexcolor = hexcolor.toString();
    var r = parseInt(hexcolor.substr(0, 2), 16);
    var g = parseInt(hexcolor.substr(2, 2), 16);
    var b = parseInt(hexcolor.substr(4, 2), 16);
    var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
    return (yiq >= 128) ? chroma(hexcolor).darken(4).hex() : 'white';
}

function toggleRead(el, ...rest) {
    var paragraph = $(el).closest('.ddd-ellipsis');
    var dot = paragraph.data('dot-api');
    var isTruncated = paragraph.hasClass('ddd-truncated');

    if (isTruncated) {
        dot.API.restore();
        $('.read-more', paragraph).focus().text('Collapse').addClass('d-block'); // add block style to force Collapse link to new line per design
    } else {
        dot.API.truncate();
        $('.read-more', paragraph).focus().text('Read More');
    }
}

function resetValidationErrors($form) {
    $('.form-group.has-error', $form).removeClass('has-error');
    $('.field-validation-error', $form)
        .removeClass('field-validation-error')
        .addClass('field-validation-valid')
        .text('');
    $form.data('validator').resetForm();
};

function displayValidationErrors(errorDictJson) {
    var errors = JSON.parse(errorDictJson);
    for (var prop in errors) {
        if (errors.hasOwnProperty(prop) && errors[prop].length) {
            $('[data-valmsg-for$="' + prop + '"]')
                .removeClass('field-validation-valid')
                .addClass('field-validation-error')
                .text(errors[prop][0])
                .closest('.form-group')
                .addClass('has-error');
        }
    }
}

function showCourseModal(id) {
    const $modal = $('#course-modal');
    $('body').addClass('busy');
    $.post('/getcoursemodal', { id: id }, function (html) {
        $('body').removeClass('busy');
        $('.modal-dialog', $modal).html(html);

        // The opacity is set in order to take a measurement of the title and set css for the tab-content to prevent a FOUC.
        // You can't get the height of a element inside a container with display:none, which is why the modal show happens before the measurement is taken
        $modal.css('opacity', 0);
        $modal.modal('show');
        setCourseModelTabContentSize($modal);
        $modal.css('opacity', 1);
    });
}

async function getSitefinityUrls(type = "") {
    const { origin } = window.location;
    const data = await $.get(`${origin}/sitefinityurls`);
    const { Data } = data || {};

    if (!!type?.length) return Data[type];
    else return Data;
}

async function getCurrentCartCount() {
    const results = await $.get("/getcurrentcartcount");
    const { count } = results || {};

    return count;
}

async function handleUpdateCurrentCart() {
    const count = await getCurrentCartCount();

    if (count != null) {
        const $cartLink = $('.nav-link.cart-link');
        const $countSpan = $('.nav-link.cart-link > span');
        if (!!$countSpan?.length) {
            $countSpan.text(count);
        } else {
            $cartLink.append(`<span>${count}</span>`);
        }
    }
}

function handleDisableOhio() {
    const disableOhio = $('.license-list-primary [data-state="OH"]')?.length > 0;
    $('#LicenseState option[value="OH"]').attr('disabled', disableOhio);
}

function removeLoaders(timeout = 5000) {
    setTimeout(() => {
        $('.loading').removeClass('loading');
        $('.busy').removeClass('busy');
    }, timeout);    
}

function setCourseModelTabContentSize($modal) {
    var offsetHeight = $('.modal-header', $modal).outerHeight() + $('.tabs-nav', $modal).outerHeight() + $('.modal-footer', $modal).outerHeight();
    $('.modal-body > .tab-content', $modal).css({ 'maxHeight': `calc(100vh - ${offsetHeight}px)` });
    var short = $('.overview-container', $modal).outerHeight() < $('.overview-wrapper', $modal).outerHeight();
    if (short) $('.overview-wrapper', $modal).addClass('h-100');
}