'use strict';
/* globals confirm, alert */

export default class ReviewsController {



	constructor($http, $window, $scope, $q, $filter, $rootScope, HostFactory, TextReview, ProductResource,
		AssignReviewstoAnalystUtils, CurrentSession, $log, User, Utils, ErrorMailer, notify,
		HtmlKeywordsUnderliner, AnalysisStats) {
		'ngInject';
		this.$http = $http;
		this.$window = $window;
		this.$rootScope = $rootScope;
		this.$q = $q;
		this.HostFactory = HostFactory;
		this.TextReview = TextReview;
		this.$scope = $scope;
		this.$rootScope = $rootScope;
		this.$log = $log;
		this.$filter = $filter;
		this.User = User;
		this.Utils = Utils;
		this.ErrorMailer = ErrorMailer;
		this.ProductResource = ProductResource;
		this.AssignReviewstoAnalystUtils = AssignReviewstoAnalystUtils;
		this.CurrentSession = CurrentSession;
		this.notify = notify;
		this.AnalysisStats = AnalysisStats;
		this.HtmlKeywordsUnderliner = HtmlKeywordsUnderliner;
		this.startOfAnalysis = null;
	}

	$onInit() {
		this.user = JSON.parse(this.$window.sessionStorage.user || null);
		this.tagsDomain = this.CurrentSession.getCurrentProduct() ? this.CurrentSession.getCurrentProduct().category : '';
		this.tagsLanguage = this.CurrentSession.getCurrentProduct() ? this.CurrentSession.getCurrentProduct().language : '';
		this.selectedText = '';
		this.currentOrigin = null;
		this.skip = 0;
		this.addWatchers();
		this.loadProducts();
		this.tagsToSuggest = [];
	}

	loadProducts() {
		this.ProductResource.queryAll().then((products) => {
			this.products = this.AssignReviewstoAnalystUtils.decodeAssignedProducts(this.User.get(), products);
			console.log(this.products);
		}, (err) => {
			alert('Oooooops: ' + JSON.stringify(err));
		});
	}

	addWatchers() {
		this.$scope.$on('selectedText', (evt, val) => {
			this.selectedText = val;
		});
		this.$scope.$on('tagSelectionClosed', () => {
			this.selectedText = null;
		});
		this.$rootScope.$on('ANNOTATION_SAVED', () => {
			this.selectedText = null;
		});
	}


	//
	//
	//
	// $scope.skip = 0;
	// // TODO: we could divide this controller in 2 components: one for the navigation (surfing reviews) and one for the annotation (to anotate reviews)
	//
	// $scope.cancellami = function(msg) {
	// 	alert('msg:' + msg);
	// };
	//

	enrichScopeWithReviewIndex(review, product, languages, datSource) {
		this.Utils.Reviews.indexOf(review, product, languages, datSource).then((data) => {
			this.reviewIndex = data.index;
			this.reviewTotal = data.total;
		}, (err) => {
			alert('Ooooooooooops: ' + JSON.stringify(err));
		});
	}


	// save functions

	saveStats() {
		var secondsSpentOnReview, analysisData;
		if (this.startOfAnalysis) {
			secondsSpentOnReview = parseInt((new Date() - this.startOfAnalysis) / 1000);
		}
		analysisData = {
			secondsSpentOnReview: secondsSpentOnReview,
			user: this.User.get(),
			language: this.review.review.language,
			product: this.product,
			review: this.review
		};
		this.AnalysisStats.save(analysisData).then(function(data) {
			this.$log.info('Stat about single analysis saved', data);
		}, function(err) {
			this.$log.info('Error', err);
		});
	}

	saveAnnotatedReview(review) {
		var def = this.$q.defer();
		if (review.aggregatedSentiment !== 0 && review.aggregatedSentiment !== 1 && review.aggregatedSentiment !== 2 && review.aggregatedSentiment !== -1 && review.aggregatedSentiment !== -2) {
			this.notify.show('Impossible to save! You need first to specify the sentiment for this review');
			def.reject(new Error('Impossible to save! You need first to specify the sentiment for this review'));
			return def.promise;
		}
		if (!review.feature2sentiment || !review.feature2sentiment.length) {
			if (!confirm('Are you sure you want to save this review without specifying any tag?')) {
				this.notify.show('Please add some tags and then click save again!');
				def.reject(new Error('Please add some tags and then click save again!'));
				return def.promise;
			}
		}

		this.HtmlKeywordsUnderliner.removeAnyUnderlying(review, true);

		this.$q.all([this._saveAnnotatedReview(review), this._incrementAnnotatedReviewsByUser(this.user)])
			.then((data) => {

				console.log('Updated user and review', data);
				this.notify.show('Review saved...');
				this.$rootScope.$emit('REVIEW_SAVED');
				def.resolve();

			}, function(err) {
				this.ErrorMailer.send({
					message: 'Error while saving annotated review or incrementing reviews annotated by users',
					reviewId: review._id
				});
				def.reject(err);
				alert('Ooooooooooops: ' + JSON.stringify(err));
			});
		return def.promise;
	}

	saveAndGoToNextReviewToAnnotate(review) {
		this.saveAnnotatedReview(review)
			.then(() => {
				this.saveStats();
				this.nextReviewToAnnotateByTitlesAndDataSource(this.CurrentSession.getCurrentProduct());
			}, (err) => {
				this.ErrorMailer.send({
					message: 'Error while saving annotated review or incrementing reviews annotated by users',
					reviewId: this.review._id
				});
				alert('Ooooooooooops: ' + JSON.stringify(err));
			});
	}

	_incrementAnnotatedReviewsByUser() {
		if (!this.user.numberOfAnnotatedReviews) {
			this.user.numberOfAnnotatedReviews = 0;
		}
		this.user.numberOfAnnotatedReviews = this.user.numberOfAnnotatedReviews + 1;
		return this.User.update(this.user);
	}

	_saveAnnotatedReview(review) {
		var now, analyst;

		now = new Date();
		analyst = this.User.get();

		if (!review.manualAnnotation) {
			review.manualAnnotation = {
				lastUpdate: now
			};
		}
		// analysis field
		if (!review.analysis) {
			review.analysis = {};
		}
		review.analysis.hasBeenManuallyAnnotated = true;
		if (!review.analysis.manualAnnotations) {
			review.analysis.manualAnnotations = [];
		}
		review.analysis.manualAnnotations.push({
			username: (analyst && analyst.username) ? analyst.username : null,
			date: now
		});


		return this.TextReview.update(review);
	}

	nextReviewToAnnotateByTitlesAndDataSource(dataSource) {
		var product = this.CurrentSession.getCurrentProduct();
		var languages, titles;

		//if (!dataSource){
		dataSource = product.dataSource || 'reviews';
		//}

		languages = [product.language];
		titles = product.reviewTitles;


		return this.$q.all([
			this.TextReview.getReviewToManuallyAnnotateByProductAndLanguagesAndDataSource(product, languages, dataSource),
			this.TextReview.countAllByProductAndLanguagesAndDataSource(product, languages, dataSource),
			this.TextReview.countManuallyAnnotatedByProductAndLanguagesAndDataSource(product, languages, dataSource),
		]).then((data) => {
			var review, numberOfReviews, numberOfAnnotatedReviews;

			review = data[0];
			numberOfReviews = data[1];
			numberOfAnnotatedReviews = data[2];
			this.startOfAnalysis = new Date();

			numberOfReviews = numberOfReviews.replace(/"/g, '');
			numberOfReviews = parseInt(numberOfReviews);
			numberOfAnnotatedReviews = numberOfAnnotatedReviews.replace(/"/g, '');
			numberOfAnnotatedReviews = parseInt(numberOfAnnotatedReviews);

			this.$log.info('numberOfReviews', numberOfReviews, numberOfAnnotatedReviews);

			this.numberOfReviews = numberOfReviews;
			this.numberOfAnnotatedReviews = numberOfAnnotatedReviews;
			this.percentageOfAnnotatedReviews = numberOfAnnotatedReviews * 100 / numberOfReviews;

			if (!review) {
				return this.TextReview.getLastAnnotatedReviewByProductAndLanguagesAndDataSource(product, languages, dataSource).then((review) => {
					if (!review) {
						return this.notify.show('No reviews for this product...');
					}
					//this.underlineTagsInsideReview(review);
					review = this.$filter('reviewHtmlEntitiesReplacer')(review);
					this.review = review;
					this.$log.info('this.review', this.review);
					this.enrichScopeWithReviewIndex(review, product, languages, dataSource);
				}, function(err) {
					this.ErrorMailer.send({
						message: 'Error while executing TextReview.getReviewToManuallyAnnotateByReviewTitles, TextReview.countAllByReviewTitles, TextReview.countManuallyAnnotatedByReviewTitles',
						titles: titles,
						'this.skip': this.skip,
						error: err
					});
					alert('Ooooooooooops: ' + JSON.stringify(err));
				});
			}

			review = this.$filter('reviewHtmlEntitiesReplacer')(review);
			this.review = review;
			//this.underlineTagsInsideReview(review);
			this.enrichScopeWithReviewIndex(review, product, languages, dataSource);
		}, function(err) {
			this.ErrorMailer.send({
				message: 'Error while executing TextReview.getReviewToManuallyAnnotateByProduct, TextReview.countAllByProduct, TextReview.countManuallyAnnotatedByProduct',
				product: product,
				'this.skip': this.skip,
				error: err
			});
			alert('Ooooooooooops: ' + JSON.stringify(err));
		});
	}
	changeProductFilter(_product) {
		var dataSource;
		var tagsDomain;

		dataSource = _product.dataSource || 'reviews';
		this.skip = 0;
		this.CurrentSession.setCurrentProduct(_product);

		this.nextReviewToAnnotateByTitlesAndDataSource(this.CurrentSession.getCurrentProduct(), dataSource);

		tagsDomain = this.CurrentSession.getCurrentProduct() ? this.CurrentSession.getCurrentProduct().category : '';
		tagsDomain = (dataSource !== 'reviews') ? tagsDomain + '-call-center' : tagsDomain;

		this.tagsDomain = tagsDomain;
		this.tagsLanguage = this.CurrentSession.getCurrentProduct() ?
			this.CurrentSession.getCurrentProduct().language : [];
		this.$rootScope.$emit('setFocus');

	}


	// start prev next functions
	previousReview(skip) {
		var product = this.CurrentSession.getCurrentProduct();
		var languages, titles;
		var dataSource;

		dataSource = product.dataSource || 'reviews';

		if (!this.review || !this.review._id) {
			return;
		}
		// languages = getLanguagesByProductAssignedToThisAnalyst(product);
		languages = [product.language];
		titles = product.reviewTitles;

		return this.TextReview.getPreviousReviewByProductAndUpperBoundIdAndLanguages(product, this.review._id, languages, skip, dataSource)
			.then((review) => {
				var notification;

				if (!review) {
					notification = this.notify.show('There are no more older reviews...');
					return;
				}
				this.startOfAnalysis = new Date();
				this.review = review;
				//$scope.underlineTagsInsideReview($scope.review);
				this.enrichScopeWithReviewIndex(review, product, languages, dataSource);
			}, (err) => {
				this.ErrorMailer.send({
					message: 'Error while going to previous review...',
					titles: titles,
					currentReviewId: this.review._id,
					error: err
				});
				alert('Ooooooooooops: ' + JSON.stringify(err));
			});
	}

	nextReview(skip) {
		var product = this.CurrentSession.getCurrentProduct();
		var titles, languages;
		var dataSource;
		dataSource = product.dataSource || 'reviews';

		if (!this.review || !this.review._id) {
			return;
		}
		titles = product.reviewTitles;
		// languages = getLanguagesByProductAssignedToThisAnalyst(product);
		languages = [product.language];
		this.TextReview.getNextReviewByProductAndLowerBoundIdAndLanguages(product, this.review._id, languages, skip, dataSource)
			.then((review) => {
				if (!review) {
					this.notify.show('There are no more reviews...');
					return;
				}

				this.startOfAnalysis = new Date();
				this.review = review;
				//$scope.underlineTagsInsideReview($scope.review);
				this.enrichScopeWithReviewIndex(review, product, languages, dataSource);
			}, (err) => {
				this.ErrorMailer.send({
					message: 'Error while going to previous review...',
					titles: titles,
					currentReviewId: this.review._id,
					error: err
				});
				alert('Ooooooooooops: ' + JSON.stringify(err));

			});
	}

	calculatePercentageString(part, total) {
		return parseInt(part * 100 / total) + '%';
	}

	// end prev next functions


	// $scope.changeSearchQuery = function(q) {
	// 	if (q && q.length > 0 && q !== '') {
	// 		$scope.areTagBoxesOpen = true;
	// 		return;
	// 	}
	// 	$scope.areTagBoxesOpen = false;
	// };
	//
	// // TODO: new funcs
	setAggregatedSentiment(aggregatedSentiment) {
		if (!this.review) {
			return;
		}
		this.review.aggregatedSentiment = aggregatedSentiment;
	}

	startDraggingTag() {
		this.areTagBoxesOpen = true;
	}

	openInsightsEditor() {
		this.$rootScope.$emit('openInsightsEditor');
	}
	toggleInsightsEditor() {
		this.$rootScope.$emit('toggleInsightsEditor');
	}
	toggleTagDictionary() {
			this.$rootScope.$emit('toggleTagDictionary');
		}
		//
		// /** Start **/
		//
		// /** Models **/
		//
		// $scope.products = [];
		// $scope.review = null;
		//
		// /** Ui **/
		//
		// $scope.isSearchFocused = true;
		// $scope.areTagBoxesOpen = false;
		// $scope.currentSession = this.CurrentSession.get();
		//
		//
		// ProductResource.queryAll().then(function(products) {
		// 	$log.info('Found', products.length, 'products', products);
		//
		// 	$scope.products = AssignReviewstoAnalystUtils.decodeAssignedProducts(User.get(), products);
		//
		// }, function(err) {
		// 	alert('Oooooops: ' + JSON.stringify(err));
		// });


}