var Wick = Wick || {};
Wick.BannerPlacementManager = {
    SPONSOR_BANNERS_DISPLAYED_EVENT: 'sponsorAdsDisplayedEvent',
    el: {
        banners: '.card-product-banner',
        sponsorBanners: '.card-sponsor-banner',
        sponsorProducts: '.card-sponsor-product',
        allBanners: '.card-product-banner, .card-sponsor-banner, .card-sponsor-product',
        productCard: '.product-card',
        allListSlots:
            '.product-card, .card-product-banner, .card-sponsor-banner, .card-sponsor-product',
        productsWrap: '.products-list-v2',
        $products: $('.product-card'),
        attrPositionDesktop: 'data-desktop-position',
        attrPositionMobile: 'data-mobile-position',
        attrRequiredAmountDesktop: 'data-required-amount-desktop',
        attrRequiredAmountMobile: 'data-required-amount-mobile',
        hide: 'd-none',
        sponsoredAdvBanners: '.sponsored-ad',
        sponsorTopBanner: '.sponsor-top-banner',
    },
    classes: {
        sponsorBanners: 'card-sponsor-banner',
        sponsorProducts: 'card-sponsor-product',
        productBanners: 'card-product-banner',
        bannerInactiveClass: 'card-product-banner--inactive',
    },
    isEventSent: false,
    currentBreakpoint: null,
    checkProductsInColumn() {
        Wick.BannerPlacementManager.addInactiveClasses();
        Wick.BannerPlacementManager.arrangeBannersInRightOrder();
        const $allBanners = $(Wick.BannerPlacementManager.el.allBanners);
        const totalProducts = Wick.BannerPlacementManager.getListLength();
        const totalSlots = totalProducts + $allBanners.length;
        $allBanners.each((index, banner) => {
            const bannerPosition = Wick.BannerPlacementManager.getBannerPosition(banner);

            if ($(banner).hasClass('card-product-banner')) {
                if (bannerPosition > totalSlots) {
                    Wick.BannerPlacementManager.hideBanner(banner);
                    $(Wick.BannerPlacementManager.el.productsWrap).append(banner);
                    return;
                }
            }

            if (
                $(banner).hasClass(Wick.BannerPlacementManager.classes.sponsorBanners) ||
                $(banner).hasClass(Wick.BannerPlacementManager.classes.sponsorProducts)
            ) {
                if (bannerPosition > totalProducts) {
                    Wick.BannerPlacementManager.showBanner(banner);
                    Wick.BannerPlacementManager.removeInactiveClass(banner);
                    $(Wick.BannerPlacementManager.el.productsWrap).append(banner);
                    return;
                }
            }

            Wick.BannerPlacementManager.hideBannerDueLimit(banner, index);
            Wick.BannerPlacementManager.moveBannerToSpecifiedPosition(banner);
        });
    },
    moveBannerToSpecifiedPosition(banner) {
        const $listSlots = Wick.BannerPlacementManager.getListSlots();
        const bannerPosition = Wick.BannerPlacementManager.getBannerPosition(banner) - 2;
        const listSlotsLength = $listSlots.length;

        if (Wick.BannerPlacementManager.isBannerVisible(banner)) {
            if (bannerPosition <= listSlotsLength) {
                if ($listSlots[bannerPosition]) {
                    Wick.BannerPlacementManager.showBanner(banner);
                    Wick.BannerPlacementManager.removeInactiveClass(banner);
                    Wick.BannerPlacementManager.moveBanner(banner, $listSlots[bannerPosition]);
                } else {
                    Wick.BannerPlacementManager.hideBanner(banner);
                    Wick.BannerPlacementManager.coverEdgeCases(banner);
                }
            } else {
                if (
                    $(banner).hasClass(Wick.BannerPlacementManager.classes.sponsorBanners) ||
                    $(banner).hasClass(Wick.BannerPlacementManager.classes.sponsorProducts)
                ) {
                    Wick.BannerPlacementManager.showBanner(banner);
                    Wick.BannerPlacementManager.removeInactiveClass(banner);
                    $(Wick.BannerPlacementManager.el.productsWrap).append(banner);
                } else {
                    Wick.BannerPlacementManager.hideBanner(banner);
                }
            }
        }
    },
    moveBanner(banner, targetElement) {
        $(banner).remove();
        $(targetElement).after(banner);
    },
    hideBanner(banner) {
        $(banner).addClass(Wick.BannerPlacementManager.el.hide);
    },
    showBanner(banner) {
        $(banner).removeClass(Wick.BannerPlacementManager.el.hide);
    },
    isBannerVisible(banner) {
        return !$(banner).hasClass(Wick.BannerPlacementManager.el.hide);
    },
    hideBannerDueLimit(banner) {
        const bannerMinLimit = Wick.BannerPlacementManager.getBannerLimit(banner) - 1;
        const $listSlots = Wick.BannerPlacementManager.getListSlots();
        const listProductsLength = $listSlots.length;
        Wick.BannerPlacementManager.showBanner(banner);

        if (bannerMinLimit > listProductsLength) {
            Wick.BannerPlacementManager.hideBanner(banner);
        }
    },
    getBannerPosition(banner) {
        const isMobile = Wick.BannerPlacementManager.isMobileResolution();
        const positionAttribute = isMobile
            ? Wick.BannerPlacementManager.el.attrPositionMobile
            : Wick.BannerPlacementManager.el.attrPositionDesktop;

        return banner.hasAttribute(positionAttribute)
            ? Number(banner.getAttribute(positionAttribute))
            : Number(
                  Wick.BannerPlacementManager.getListLength() +
                      Wick.BannerPlacementManager.getBannersAmount()
              );
    },
    getBannerLimit(banner) {
        const isMobile = Wick.BannerPlacementManager.isMobileResolution();

        const limitAttribute = isMobile
            ? Wick.BannerPlacementManager.el.attrRequiredAmountMobile
            : Wick.BannerPlacementManager.el.attrRequiredAmountDesktop;

        return banner.hasAttribute(limitAttribute)
            ? Number(banner.getAttribute(limitAttribute))
            : 0;
    },
    isMobileResolution() {
        return Wick.Responsive.getCurrentBreakpoint() !== 'up-lg';
    },
    getListLength() {
        const $listItems = $(Wick.BannerPlacementManager.el.productsWrap).children(
            Wick.BannerPlacementManager.el.productCard
        );
        return $listItems.length;
    },
    getBannersAmount() {
        return $(Wick.BannerPlacementManager.el.allBanners).length;
    },
    getProductsAmount() {
        return Wick.BannerPlacementManager.el.$products.length;
    },
    arrangeBannersInRightOrder() {
        const $allBanners = $(Wick.BannerPlacementManager.el.allBanners);

        const sponsorProducts = $allBanners.filter((i, el) =>
            $(el).hasClass(Wick.BannerPlacementManager.classes.sponsorProducts)
        );
        const sponsorBanners = $allBanners.filter((i, el) =>
            $(el).hasClass(Wick.BannerPlacementManager.classes.sponsorBanners)
        );

        const firstSponsorProductPos =
            sponsorProducts.length > 0
                ? Math.min(
                      ...sponsorProducts
                          .map((i, el) => Wick.BannerPlacementManager.getBannerPosition(el))
                          .get()
                  )
                : Infinity;
        const firstSponsorBannerPos =
            sponsorBanners.length > 0
                ? Math.min(
                      ...sponsorBanners
                          .map((i, el) => Wick.BannerPlacementManager.getBannerPosition(el))
                          .get()
                  )
                : Infinity;

        let groupOrder;
        if (firstSponsorProductPos < firstSponsorBannerPos) {
            groupOrder = [
                Wick.BannerPlacementManager.classes.sponsorProducts,
                Wick.BannerPlacementManager.classes.sponsorBanners,
                Wick.BannerPlacementManager.classes.productBanners,
            ];
        } else {
            groupOrder = [
                Wick.BannerPlacementManager.classes.sponsorBanners,
                Wick.BannerPlacementManager.classes.sponsorProducts,
                Wick.BannerPlacementManager.classes.productBanners,
            ];
        }

        $allBanners
            .sort((a, b) => {
                function getGroupIndex(el) {
                    if ($(el).hasClass(groupOrder[0])) return 0;
                    if ($(el).hasClass(groupOrder[1])) return 1;
                    if ($(el).hasClass(groupOrder[2])) return 2;
                    return 3;
                }

                const groupA = getGroupIndex(a);
                const groupB = getGroupIndex(b);

                if (groupA !== groupB) {
                    return groupA - groupB;
                }

                const positionA = Wick.BannerPlacementManager.getBannerPosition(a);
                const positionB = Wick.BannerPlacementManager.getBannerPosition(b);

                return positionA - positionB;
            })
            .appendTo(Wick.BannerPlacementManager.el.productsWrap);
    },
    addInactiveClasses() {
        $(Wick.BannerPlacementManager.el.allBanners).addClass(Wick.BannerPlacementManager.el.hide);
    },
    removeInactiveClass(banner) {
        $(banner).removeClass(Wick.BannerPlacementManager.classes.bannerInactiveClass);
    },
    insertFirstBanner(banner) {
        const bannerPosition = Wick.BannerPlacementManager.getBannerPosition(banner);

        if (bannerPosition === 1) {
            Wick.BannerPlacementManager.showBanner(banner);
            Wick.BannerPlacementManager.removeInactiveClass(banner);
            $(banner).remove();
            $(Wick.BannerPlacementManager.el.productsWrap).prepend(banner);
        }
    },
    coverEdgeCases(banner) {
        Wick.BannerPlacementManager.insertFirstBanner(banner);
    },
    getListSlots() {
        return $(Wick.BannerPlacementManager.el.productsWrap)
            .children(Wick.BannerPlacementManager.el.allListSlots)
            .filter(function () {
                if ($(this).hasClass(Wick.BannerPlacementManager.classes.productBanners)) {
                    const position = Wick.BannerPlacementManager.getBannerPosition(this);
                    const productsCount = Wick.BannerPlacementManager.getListLength();
                    return position <= productsCount;
                }

                return true;
            });
    },
    getBannerPriority(banner) {
        if ($(banner).hasClass(Wick.BannerPlacementManager.classes.sponsorProducts)) {
            return 1;
        }
        if ($(banner).hasClass(Wick.BannerPlacementManager.classes.sponsorBanners)) {
            return 2;
        }
        return 3;
    },
    dispatchSponsorAdsDisplayedEvent() {
        return new Promise((resolve, reject) => {
            const eventDetail = { resolve, reject };
            const sponsorAdsEvent = createEvent(
                Wick.BannerPlacementManager.SPONSOR_BANNERS_DISPLAYED_EVENT,
                { displayed: true },
                eventDetail
            );
            window.dispatchEvent(sponsorAdsEvent);
        });
    },
    init() {
        Wick.Responsive.onResize(function () {
            if (
                Wick.BannerPlacementManager.currentBreakpoint !==
                Wick.Responsive.getCurrentBreakpoint()
            ) {
                Wick.BannerPlacementManager.currentBreakpoint =
                    Wick.Responsive.getCurrentBreakpoint();
                Wick.BannerPlacementManager.checkProductsInColumn();

                if (
                    !Wick.BannerPlacementManager.isEventSent &&
                    $(Wick.BannerPlacementManager.el.sponsoredAdvBanners).length
                ) {
                    Wick.BannerPlacementManager.dispatchSponsorAdsDisplayedEvent();
                    Wick.BannerPlacementManager.isEventSent = true;
                }

                $(window).trigger('productBannerPositionChanged');
            }
        });
    },
};

$(document).ready(function () {
    const hasBanners = Wick.BannerPlacementManager.getBannersAmount();
    const hasTopBanner = $(Wick.BannerPlacementManager.el.sponsorTopBanner).length;
    const hasProducts = Wick.BannerPlacementManager.getProductsAmount();

    if ((!hasBanners && !hasTopBanner) || !hasProducts) {
        return;
    }

    Wick.BannerPlacementManager.init();
});
