export default class CatalogController {



    constructor($scope, $log, $q, $rootScope, RealtimeProductResource, DataCalculator, TextReview, RealtimeUserForAdministrator, Tag, notify) {
        'ngInject';
        this.$scope = $scope;
        this.$log = $log;
        this.$rootScope = $rootScope;
        this.RealtimeProductResource = RealtimeProductResource;
        this.DataCalculator = DataCalculator;
        this.TextReview = TextReview;
        this.RealtimeUserForAdministrator = RealtimeUserForAdministrator;
        this.Tag = Tag;
        this.notify = notify;
        this.ProductEventNamesByHttpMethods = this.RealtimeProductResource.getRestEventNames();
        this.UserForAdministratorEventNamesByHttpMethods = this.RealtimeUserForAdministrator.getRestEventNames();
    }

    $onInit() {
        this.products = [];
        this.tmpProducts = [];
        this.analysts = [];
        this.page = 0;
        this.areThereMoreProducts = true;
        this.isLoadingNewPage = false;
        //this.getAllAnalystsAndAdministratorsFromUserForAdministrator();
        this.getPage();
        this.getTagsDomain();
        this.registerEvents();
    }

    registerEvents() {
        // updates coming from other users
        this.$rootScope.$on(this.ProductEventNamesByHttpMethods.POST, (e, product) => {
            this.$log.info('Some collaborative user created a product', product);
            this.products.push(product);
            this.initializeProducts();
            this.tmpProducts.push(product);
            this.$scope.$apply();
        });

        this.$rootScope.$on(this.ProductEventNamesByHttpMethods.PUT, (e, product) => {
            this.$log.info('Some collaborative user updated a product', product);
            this.products.every((el, index) => {
                if (el && product && el._id === product._id) {
                    this.products[index] = product;
                    this.tmpProducts[index] = product;
                    return false;
                }
                return true;
            });
            this.initializeProducts();
            this.$scope.$apply();


        });

        this.$rootScope.$on(this.ProductEventNamesByHttpMethods.DELETE, (e, product) => {
            this.$log.info('Some collaborative user deleted a product', product);
            this.products.every((el, index) => {
                if (el._id === product._id) {
                    this.products.splice(index, 1);
                    // this.products[index] = product;
                    this.$scope.$apply();
                    return false;
                }
                return true;
            });
        });
        // TODO: this could be removed, because analysts are not managed inside the "product" section, but inside the subsection "analyst"...
        this.$rootScope.$on(this.UserForAdministratorEventNamesByHttpMethods.POST, (e, analyst) => {
            this.$log.info('Some collaborative user created an analyst', analyst);
            this.analysts.push(analyst);
        });

        // TODO: this could be removed, because analysts are not managed inside the "product" section, but inside the subsection "analyst"...
        this.$rootScope.$on(this.UserForAdministratorEventNamesByHttpMethods.PUT, (e, analyst) => {
            this.$log.info('Some collaborative user updated an analyst', analyst);
            this.analysts.every((el, index) => {
                if (el._id === analyst._id) {
                    this.analysts[index] = analyst;
                    this.$scope.$apply();
                    return false;
                }
                return true;
            });
        });

        // TODO: this could be removed, because analysts are not managed inside the "product" section, but inside the subsection "analyst"...
        this.$rootScope.$on(this.UserForAdministratorEventNamesByHttpMethods.DELETE, (e, analyst) => {
            this.$log.info('Some collaborative user deleted an analyst', analyst);
            this.analysts.every((el, index) => {
                if (el._id === analyst._id) {
                    this.analysts.splice(index, 1);
                    this.analysts[index] = analyst;
                    this.$scope.$apply();
                    return false;
                }
                return true;
            });
        });
    }

    getTagsDomain() {
        this.Tag.getAllDomains().then((categories) => {
            this.categories = categories;
        }).catch((err) => {
            alert('Error: \n' + JSON.stringify(err, null, 4));
        });
    }



    getPage() {
        this.isLoadingNewPage = true;
        return this.RealtimeProductResource.queryAllWithoutInsightsByPage(this.page)
            .then((products) => {
                this.products = this.products.concat(products);
                this.initializeProducts();
                this.tmpProducts = this.products.map((el) => {
                    var copy;
                    copy = angular.copy(el);
                    // copy.reviewTitle2sku = (copy.reviewTitle2sku) ? copy.reviewTitle2sku : {};
                    copy.urls = copy.urls ? copy.urls : [];
                    return copy;
                });
                this.$log.info(this.products);
                return this.products;
            })
            .then((products) => {
                angular.forEach(products, function(product, key) {
                    console.log(product.reviewTitles);
                });
                if (products.length < 40) {
                    this.areThereMoreProducts = false;
                }
            })
            .catch((err) => {
                alert('Oooooooooops: an error occured while getting products...' + JSON.stringify(err));
            })
            .finally(() => {
                this.isLoadingNewPage = false;
            });
    }

    getSKUFromInfoArrayByTitle(product, title) {
        var matchSKUTitlePair;
        if (product.reviewTitlesInfo) {
            matchSKUTitlePair = product.reviewTitlesInfo.find(
                function(SKUTitlePair, title) {
                    console.log(SKUTitlePair, title);
                    return (SKUTitlePair.name === title);
                }
            );
        }
        return matchSKUTitlePair ? matchSKUTitlePair.sku : null;
    }

    initializeProducts() {
        this.products = this.products.map((el) => {
            el.reviewTitlesInfo = (el.reviewTitlesInfo) ? el.reviewTitlesInfo : [];
            el.reviewTitles = (el.reviewTitles) ? el.reviewTitles : [];
            el.reviewTitles.forEach(function(reviewTitle) {
                const pair = el.reviewTitlesInfo.find(pair => pair.title === reviewTitle);
                if (!pair) {
                    el.reviewTitlesInfo.push({
                        title: reviewTitle
                    });
                }
            });
            el.reviewTitlesInfo.sort(function(e1, e2) {
                return e1.title < e2.title;
            });
            return el;
        });
    }

    // editing
    addReviewTitle(product, reviewTitle) {
        this.RealtimeProductResource.addReviewTitleByProductAndReviewTitle(product, reviewTitle)
            .then((newProduct) => {
                product.reviewTitles = newProduct.reviewTitles;
                this.initializeProducts();
                this.$log.info('Product updated!');
                this.notify.show('Product updated','/img/notify.png');
            }, (err) => {
                this.$log.info('Error', err);
                this.notify.show('Error while updating the product','/img/notify.png');
            });
    };

    changeBrandName(product, newBrandName) {
        this.RealtimeProductResource.setBrandNameByProductAndBrandName(product, newBrandName).then((doc) => {
            product.brandName = doc.brandName;
            this.$log.info('Product updated!');
            this.notify.show('Product updated','/img/notify.png');
        }, (err) => {
            this.$log.info('Error', err);
            this.notify.show('Error while updating the product','/img/notify.png');
        });
    };

    changeImageUrl(product, newImageUrl) {
        this.RealtimeProductResource.setImageUrlByProductAndImageUrl(product, newImageUrl).then((doc) => {
            product.imageUrl = doc.imageUrl;
            this.$log.info('Product updated!');
            this.notify.show('Product updated','/img/notify.png');
        }, (err) => {
            this.$log.info('Error', err);
            this.notify.show('Error while updating the product','/img/notify.png');
        });
    };

    changeDeliveryDate(product, newDeliveryDate) {
        this.RealtimeProductResource.setDeliveryDateByProductAndDeliveryDate(product, newDeliveryDate).then((doc) => {
            product.deliveryDate = doc.deliveryDate;
            this.$log.info('Product updated!');
            this.notify.show('Product updated','/img/notify.png');
        }, (err) => {
            this.$log.info('Error', err);
            this.notify.show('Error while updating the product','/img/notify.png');
        });
    };

    changeProductCategory(product, newProductCategory) {
        this.RealtimeProductResource.setProductCategoryByProductAndProductCategory(product, newProductCategory).then((doc) => {
            product.category = doc.category;
            this.$log.info('Product updated!');
            this.notify.show('Product updated','/img/notify.png');
        }, (err) => {
            this.$log.info('Error', err);
            this.notify.show('Error while updating the product','/img/notify.png');
        });
    };

    changeProductName(product, newProductName) {
        this.RealtimeProductResource.setProductNameByProductAndProductName(product, newProductName).then((doc) => {
            // product.productName = doc.productName;
            product.productName = doc.productName;
            this.$log.info('Product updated!');
            this.notify.show('Product updated','/img/notify.png');
            // $scope.$apply();
            // $log.info('------------------>', product.productName)
        }, (err) => {
            this.$log.info('Error', err);
            this.notify.show('Error while updating the product','/img/notify.png');
        });
    };

    changePriceCategory(product, newPriceCategory) {
        this.RealtimeProductResource.setPriceCategoryByProductAndPriceCategory(product, newPriceCategory).then((doc) => {
            product.priceCategory = doc.priceCategory;
            this.$log.info('Product updated!');
            this.notify.show('Product updated','/img/notify.png');
        }, (err) => {
            this.$log.info('Error', err);
            this.notify.show('Error while updating the product','/img/notify.png');
        });
    };

    addCompanyId(product, companyId) {
        this.RealtimeProductResource.addCompanyIdByProductAndCompanyId(product, companyId).then((doc) => {
            this.$log.info('Product updated!');
            this.notify.show('Product updated','/img/notify.png');
            product.companyIds = doc.companyIds;
        }, (err) => {
            this.$log.info('Error', err);
            this.notify.show('Error while updating the product','/img/notify.png');
        });
    };

    delete(index, product) {
        this.RealtimeProductResource.delete(product).then(() => {
            this.products.splice(index, 1);
            this.$log.info('Product deleted');
            this.notify.show('Product deleted!','/img/notify.png');
            this.products.splice(index, 1);
        }, (err) => {
            this.$log.info('Error', err);
            this.notify.show('Error while deleting the product','/img/notify.png');
        });
    };

    saveInsights(product, insights) {
        this.RealtimeProductResource.setInsightsByProductAndInsights(product, insights).then((doc) => {
            this.$log.info('Successfully updated');
            this.notify.show('Insights saved!','/img/notify.png');
            product.insights = doc.insights;
        }, (err) => {
            alert('Ooooooooops: error' + JSON.stringify(err));
            this.notify.show('Error while updating the product','/img/notify.png');
        });
    };

    updateNumberOfReviews(product) {
        this.RealtimeProductResource.updateNumberOfReviews(product).then((doc) => {
            product.totalNumberOfReviews = doc.totalNumberOfReviews;
            product.numberOfSampledReviews = doc.numberOfSampledReviews;
            product.numberOfAnalyzedReviews = doc.numberOfAnalyzedReviews;
            product.numberOfAnalyzedAndPublishedReviews = doc.numberOfAnalyzedAndPublishedReviews;
            product.numberOfAnalyzedAndUnpublishedReviews = doc.numberOfAnalyzedAndUnpublishedReviews;
            this.$log.info('Updated product with number of reviews: ' + product.numberOfReviews);
            this.notify.show('Product updated','/img/notify.png');
        }, (err) => {
            this.$log.info('Error: ' + JSON.stringify(err));
            this.notify.show('Error while updating number of reviews for a product','/img/notify.png');
            alert(JSON.stringify(err, null, 4));
        });
    };

    updatePriceRange(product, min, max) {
        if (!product || !min || !max || min === '' || max === '') {
            return;
        }
        this.RealtimeProductResource.setPriceRangeByProductAndMinPriceAndMaxPrice(product, min, max).then((doc) => {
            this.$log.info('Successfully updated');
            this.notify.show('Update product!','/img/notify.png');
            product.priceRange = doc.priceRange;
        }, (err) => {
            this.notify.show('Error while updating product...','/img/notify.png');
            this.alert('Ooooooooops: error' + JSON.stringify(err));
        });
    };

    addProduct(productToAdd) {
        this.RealtimeProductResource.create(productToAdd).then((doc) => {
            this.$log.info('Product added successfully...');
            this.notify.show('New product saved','/img/notify.png');
            this.products.push(doc);
        }, (err) => {
            this.$log.info('Error', err);
            this.notify.show('Error while adding a product','/img/notify.png');
            alert('Ooooops: ' + JSON.stringify(err));
        });
    };

    updateChannels(product) {
        this.RealtimeProductResource
            .updateChannels(product)
            .then((doc) => {
                this.$log.info('Updated product with channels: ' + doc);
                this.notify.show(product.brandName + ' ' + product.productName + ' - ' + 'Updated channels');
            })
            .catch((err) => {
                this.$log.info('Error: ' + JSON.stringify(err));
                this.notify.show('Error while updating channels...','/img/notify.png');
            });
    };

    addCountryToProduct(newCountry, product) {
        this.RealtimeProductResource.addCountryByProductAndCountry(product, newCountry).then((doc) => {
            this.$log.info('Updated product', doc);
            this.notify.show('Updated product!','/img/notify.png');
            product.countries = doc.countries;
        }, (err) => {
            this.$log.info('Error: ' + JSON.stringify(err));
            this.notify.show('Error while updating channels...','/img/notify.png');
        });
    };

    removeCountryFromProduct(country, product) {
        this.RealtimeProductResource.removeCountryByProductAndCountry(product, country).then((doc) => {
            this.$log.info('Updated product', doc);
            this.notify.show('Updated product!','/img/notify.png');
            product.countries = doc.countries;
        }, (err) => {
            this.$log.info('Error: ' + JSON.stringify(err));
            this.notify.show('Error while updating channels...','/img/notify.png');
        });
    };

    updateMinAndMaxDate(product) {
        this.RealtimeProductResource.updateMinAndMaxDate(product).then((doc) => {
            this.$log.info('Updated min and max date: ', doc.minDate, doc.maxDate);
            product.minDate = doc.minDate;
            product.maxDate = doc.maxDate;
        }, (err) => {
            this.$log.info('Error: ' + JSON.stringify(err));
        });
    };

    updateAverageRating(product, isBasedOnRawTextReviews) {
        return this.RealtimeProductResource.updateAverageRatingByProductAndIsBasedOnRawTextReviews(product, isBasedOnRawTextReviews).then((doc) => {
            this.notify.show('Product updated!','/img/notify.png');
            this.$log.info('Successfully updated');
            this.$log.info('-->', product.avgRating, doc.avgRating);
            product.avgRating = doc.avgRating;
            this.$log.info('-->', product.avgRating, doc.avgRating);
            return doc;
        }, (err) => {
            this.$log.info('Error: ' + JSON.stringify(err));
        });
    };

    toggleVisibilityInEnterpriseDashboardApp(product) {
        var newVisibility = !product.isVisibleInEnterpriseDashboardApp;
        // product.isVisibleInEnterpriseDashboardApp = !product.isVisibleInEnterpriseDashboardApp;
        this.RealtimeProductResource.setVisibilityInEnterpriseDashboardAppByProductAndNewVisibility(product, newVisibility).then((doc) => {
            this.notify.show('Product updated!','/img/notify.png');
            this.$log.info('Successfully updated');
            product.isVisibleInEnterpriseDashboardApp = doc.isVisibleInEnterpriseDashboardApp;
        }, (err) => {
            this.notify.show('Problem while updating the product...','/img/notify.png');
            alert('Ooooooooops: error' + JSON.stringify(err));
        });
    };

    toggleVisibilityInAnnotationApp(product) {
        var newVisibility = !product.isVisibleInAnnotationApp;

        this.RealtimeProductResource.setVisibilityInAnnotationAppByProductAndNewVisibility(product, newVisibility).then((doc) => {
            this.notify.show('Product updated!','/img/notify.png');
            this.$log.info('Successfully updated');
            product.isVisibleInAnnotationApp = doc.isVisibleInAnnotationApp;
        }, (err) => {
            this.notify.show('Error while updating product!','/img/notify.png');
            alert('Ooooooooops: error' + JSON.stringify(err));
        });
    };

    updateLanguages(product) {
        this.RealtimeProductResource.updateLanguagesByProduct(product).then((doc) => {
            this.notify.show('Product updated!','/img/notify.png');
            this.$log.info('Successfully updated');
            product.languages = doc.languages;
        }, (err) => {
            this.notify.show('Error while updating product!','/img/notify.png');
            alert('Ooooooooops: error' + JSON.stringify(err));
        });
    };

    addSkuByProductAndSku(product, sku) {
        this.RealtimeProductResource.addSkuByProductAndSku(product, sku).then((doc) => {
            this.notify.show('Product updated!','/img/notify.png');
            this.$log.info('Successfully updated', doc);
            product.skus = doc.skus;
        }, (err) => {
            this.notify.show('Error while updating product!','/img/notify.png');
            alert('Ooooooooops: error' + JSON.stringify(err));
        });
    };

    changeSkuByProductAndSkuAndReviewTitle(product, sku, reviewTitle, oldSKU) {
        if (!product || !reviewTitle || !sku) {
            return alert('Ooooooooops: error - !product || !reviewTitle || !sku');
        }
        this.RealtimeProductResource.addReviewTitle2SkuByProductAndReviewTitleAndSku(product, reviewTitle, sku, oldSKU)
            .then((doc) => {
                this.notify.show('Product updated!','/img/notify.png');
                this.$log.info('Successfully updated', doc, product);
            }, (err) => {
                this.notify.show('Error while updating product!','/img/notify.png');
                // restore previous value
                for (var i = 0; i < product.reviewTitlesInfo.length; i++) {
                    if (product.reviewTitlesInfo[i].title === reviewTitle) {
                        product.reviewTitlesInfo[i].sku = oldSKU;
                    }
                }
                alert('Ooooooooops: error' + JSON.stringify(err));
            });
    };

    removeSkuByProductAndSku(product, sku) {
        this.RealtimeProductResource.removeSkuByProductAndSku(product, sku).then((doc) => {
            this.notify.show('Product updated!','/img/notify.png');
            this.$log.info('Successfully updated', doc);
            product.skus = doc.skus;
        }, (err) => {
            this.notify.show('Error while updating product!','/img/notify.png');
            alert('Ooooooooops: error' + JSON.stringify(err));
        });
    };

    publishAllAnalyzedAndUnpublishedReviews(product) {
        this.TextReview.publishAllAnalyzedAndUnpublishedReviewsByProduct(product)
            .then(() => {
                return this.RealtimeProductResource.updateNumberOfReviews(product);
            })
            .then((doc) => {
                product.totalNumberOfReviews = doc.totalNumberOfReviews;
                product.numberOfSampledReviews = doc.numberOfSampledReviews;
                product.numberOfAnalyzedReviews = doc.numberOfAnalyzedReviews;
                product.numberOfAnalyzedAndPublishedReviews = doc.numberOfAnalyzedAndPublishedReviews;
                product.numberOfAnalyzedAndUnpublishedReviews = doc.numberOfAnalyzedAndUnpublishedReviews;
            })
            .catch((msg) => {
                return alert('Oooops: error...' + msg);
            });
    };


    nextPage() {
        this.page = this.page + 1;
        this.getPage();
    };



}