module insite.catalog {
    "use strict";

    export interface IProductRecommendationsCarouselAttributes extends IProductCarouselAttributes {
        widgetPosition: number;
    }

    export class ProductRecommendationsCarouselController extends ProductCarouselController {
        productsRecommendedIds: string[];
        productsRecommended: {};

        static $inject = [...ProductCarouselController.$inject, "coreService", "productRecommendationsService"];

        constructor(
            protected cartService: cart.ICartService,
            protected productService: IProductService,
            protected $timeout: ng.ITimeoutService,
            protected addToWishlistPopupService: wishlist.AddToWishlistPopupService,
            protected settingsService: core.ISettingsService,
            protected $scope: ng.IScope,
            protected $attrs: IProductRecommendationsCarouselAttributes,
            protected queryString: common.IQueryStringService,
            protected $stateParams: IProductListStateParams,
            protected brandService: brands.IBrandService,
            protected $window: ng.IWindowService,
            protected coreService: core.ICoreService,
            protected productRecommendationsService: ProductRecommendationsService) {
            super(cartService, productService, $timeout, addToWishlistPopupService, settingsService, $scope, $attrs,
                queryString, $stateParams, brandService, $window)
        }

        $onInit(): void {
            super.$onInit();

            this.$scope.$on("productRecommendationsLoaded", (event: ng.IAngularEvent, productsRecommendations: any[]) => {
                if (!this.productSettings.enableProductRecommendations) {
                    return;
                }

                let widgetPosition = this.$attrs.widgetPosition || 1;

                // validation: make sure widgetPosition less than or equal productsRecommendations
                if (widgetPosition > productsRecommendations.length) {
                    this.productsRecommended = [];
                    this.productRecommendationsService.printError("Widget position value greater than products recommendations response");
                    return;
                }

                // widgetPosition starting from 1 so we need to subtract 1 from the value
                widgetPosition -= 1;

                const productRecommendation = productsRecommendations[widgetPosition];
                this.productRecommendationsService.print("Recommended Products - selected ", productRecommendation);

                const recs = productRecommendation["recs"] || [];
                if (recs.length === 0) {
                    return;
                }

                this.productsRecommended = this.extractProductsRecommendedData(recs);
                this.productsRecommendedIds = recs.slice(0, this.numberOfProductsToDisplay).map(o => o.refCode);
                this.getCrossSells();
            });
        }

        private extractProductsRecommendedData(productsRecommended: any) {
            const response = {};
            productsRecommended.forEach(item => {
                response[`${item.refCode}`] = item.id;
            });

            return response;
        }

        protected getCrossSells(): void {
            if (typeof (this.productSettings) === "undefined") {
                return;
            }

            if (this.productsRecommendedIds) {
                this.productService
                    .getProducts({ erpNumbers: this.productsRecommendedIds } as IProductCollectionParameters)
                    .then(
                        (productCollection: ProductCollectionModel) => {
                            productCollection.products = this.productsRecommendedIds.map(o => productCollection.products.find(p => p.erpNumber === o)).filter(o => !!o);
                            this.getProductsCompleted(productCollection);
                            this.sendImpressionTracking(productCollection.products);
                        },
                        (error: any) => { this.getProductsFailed(error); });
            }
        }

        protected sendImpressionTracking(products: ProductDto[]) {
            const recommendationIDs = [];

            products.forEach(product => {
                // id means "response id"
                const id = this.productsRecommended[product.erpNumber];
                if(id)
                    recommendationIDs.push(id);
            });
            if (recommendationIDs.length)
                this.productRecommendationsService.sendImpressionTracking(recommendationIDs);
        }

        addToCart(product: ProductDto): void {
            this.sendProductRecommendationTrackForSamePage(product);
            super.addToCart(product);
        }

        protected sendProductRecommendationTrackForPDP(product: ProductDto) {
            this.productRecommendationsService.sendProductRecommendationTrack(this.findId(product), true);
            this.coreService.redirectToPath(product.productDetailUrl);
        }


        protected sendProductRecommendationTrackForSamePage(product: ProductDto) {
            this.productRecommendationsService.sendProductRecommendationTrack(this.findId(product));
        }

        protected findId(product: ProductDto) {
            return this.productsRecommended[product.erpNumber];
        }
    }

    angular
        .module("insite")
        .controller("ProductRecommendationsCarouselController", ProductRecommendationsCarouselController);
}