
import './qualitycheck.css';
import angular from 'angular';
import uirouter from 'angular-ui-router';

var QualitycheckController = function($scope, $q, $log, $rootScope, TextReview, RawTextReview, ProductResource) {

		$scope.dataFromQualityCheckOnRawTextReviews = [];
		$scope.dataFromQualityCheckOnAnalyzedReviews = [];

		$scope.currentQueryForRawTextReviews = null;
		$scope.currentQueryForAnalyzedReviews = null;

    console.log('controller!!!!!!!!!');
		$scope.isQualityCheckUpdating = false;

		$rootScope.$on('ProductFilter.filterByProduct', function(e, product) {
			$scope.currentQueryForRawTextReviews = {
				'title': {
					$in: product.reviewTitles || []
				}
			};
			$scope.currentQueryForAnalyzedReviews = {
				'review.title': {
					$in: product.reviewTitles || []
				}
			};
			loadData();
		});
		$rootScope.$on('ProductFilter.removeCurrentFilter', function() {
			$scope.currentQueryForAnalyzedReviews = null;
			$scope.currentQueryForRawTextReviews = null;
			loadData();
		});



		function QualityCheckRunner(opts) {
			opts = opts || {};
			this.api = opts.api || null;
			this.apiName = opts.apiName || null;
			this.isNullValue = opts.isNullValue || [];
			this.isLongerThan = opts.isLongerThan || [];
			this.isGreaterThan = opts.isGreaterThan || [];
			this.isLessThan = opts.isLessThan || [];
			this.isType = opts.isType || [];
			if (!this.api) {
				throw new Error('Please provide an API object');
			}
		}
		QualityCheckRunner.prototype._enrichQuery = function(query) {
			var serviceName, tmp, tmp2, fieldName, enrichingParametersName;

			$log.info('>>>> Enriching Query!');

			serviceName = this.apiName;
			fieldName = (serviceName === 'RawTextReview') ? 'title' : 'review.title';
			enrichingParametersName = (serviceName === 'RawTextReview') ? 'currentQueryForRawTextReviews' : 'currentQueryForAnalyzedReviews';
			if (!$scope[enrichingParametersName]) {
				return query;
			}
			if (typeof query[fieldName] !== 'undefined') {
				tmp = angular.copy(query[fieldName]);
				delete query[fieldName];
				query['+$and'] = [];
				tmp2 = {};
				tmp2[fieldName] = tmp;
				query['+$and'].push(tmp2);
				tmp2 = {};
				tmp2[fieldName] = $scope[enrichingParametersName].title;
				query['+$and'].push(tmp2);
			} else {
				query[fieldName] = $scope[enrichingParametersName][fieldName];
			}
			return query;
		};
		QualityCheckRunner.prototype.run = function() {
			var result = [];
			return $q.all([
				this.countReviewsWithoutFieldByFieldName(),
				this.countReviewsWhoseFieldIsLongerThanExpected(),
				this.countReviewsWhoseFieldIsGreaterThanExpected(),
				this.countReviewsWhoseFieldIsLessThanExpected(),
				this.countReviewsWhoseFieldHaveDifferentTypeThanExpected()
			]).then(function(res) {
				res.forEach(function(arr) {
					arr.filter(function(el) {
						return el !== null && typeof el !== 'undefined';
					}).forEach(function(el) {
						result.push(el);
					});
				});
				$log.info('>>>> QualityChecker: Result', result);
				return result;
			});
		};
		QualityCheckRunner.prototype.countReviewsWithoutFieldByFieldName = function() {
			var promises;
			var self = this;
			promises = this.isNullValue.map(function(fieldName) {
				var query = {};
				query[fieldName] = null;
				query = self._enrichQuery(query);
				$log.info('>>> Query is', query);
				return self.api.count(query)
					.then(function(count) {
						count = parseInt(count.replace(/"/gi, ''));
						if (count === 0 || isNaN(count)) {
							return null;
						}
						return {
							type: 'has "null" as value',
							fieldName: fieldName,
							numberOfReviews: count,
							query: query
						};
					});
			});
			return $q.all(promises);
		};

		QualityCheckRunner.prototype.countReviewsWhoseFieldIsLongerThanExpected = function() {
			var self = this;
			var promises;
			promises = this.isLongerThan.map(function(field) {
				var maxLength = field.maxLength;
				var fieldName = field.fieldName;
				var query = {};
				query['+$where'] = 'return this.' + fieldName + ' && this.' + fieldName + '.length > ' + maxLength;
				query = self._enrichQuery(query);
				$log.info('>>> Query is', query);
				return self.api.count(query)
					.then(function(count) {
						count = parseInt(count.replace(/"/gi, ''));
						if (count === 0 || isNaN(count)) {
							return null;
						}
						return {
							type: 'is longer than ' + maxLength,
							fieldName: fieldName,
							numberOfReviews: count,
							query: query
						};
					});
			});
			return $q.all(promises);
		};
		QualityCheckRunner.prototype.countReviewsWhoseFieldIsGreaterThanExpected = function() {
			var self = this;
			var promises;
			promises = this.isGreaterThan.map(function(field) {
				var upperBound = field.upperBound;
				var fieldName = field.fieldName;
				var query = {};
				query[fieldName] = {
					'+$gt': upperBound
				};
				query = self._enrichQuery(query);
				$log.info('>>> Query is', query);
				return self.api.count(query)
					.then(function(count) {
						count = parseInt(count.replace(/"/gi, ''));
						if (count === 0 || isNaN(count)) {
							return null;
						}
						return {
							type: 'greater than ' + upperBound,
							fieldName: fieldName,
							numberOfReviews: count,
							query: query

						};
					});
			});
			return $q.all(promises);
		};
		QualityCheckRunner.prototype.countReviewsWhoseFieldIsLessThanExpected = function() {
			var self = this;
			var promises;
			promises = this.isLessThan.map(function(field) {
				var lowerBound = field.lowerBound;
				var fieldName = field.fieldName;
				var query = {};
				query[fieldName] = {
					'+$lt': lowerBound
				};
				query = self._enrichQuery(query);
				$log.info('>>> Query is', query);
				return self.api.count(query)
					.then(function(count) {
						count = parseInt(count.replace(/"/gi, ''));
						if (count === 0 || isNaN(count)) {
							return null;
						}
						return {
							type: 'is less than ' + lowerBound,
							fieldName: fieldName,
							numberOfReviews: count,
							query: query
						};
					});
			});
			return $q.all(promises);
		};
		QualityCheckRunner.prototype.countReviewsWhoseFieldHaveDifferentTypeThanExpected = function() {
			var self = this;
			var promises;
			promises = this.isType.map(function(field) {
				var expectedType = field.expectedType;
				var fieldName = field.fieldName;
				var query = {};
				query['+$where'] = 'return this.' + fieldName + ' && !(this.' + fieldName + ' instanceof ' + expectedType + ')';
				query = self._enrichQuery(query);
				$log.info('>>> Query is', query);
				return self.api.count(query)
					.then(function(count) {
						count = parseInt(count.replace(/"/gi, ''));
						if (count === 0 || isNaN(count)) {
							return null;
						}
						return {
							type: 'has wrong type',
							fieldName: fieldName,
							numberOfReviews: count,
							query: query
						};
					});
			});
			return $q.all(promises);
		};

		$scope.showProductNamesByIssue = function(issue, areRawTextReviews) {
			var promise, query;

			query = issue.query;
			$scope.issueRelatedProducts = null;

			if (areRawTextReviews) {
				promise = RawTextReview.distinct('title', query);
			} else {
				promise = TextReview.distinct('review.title', query);
			}

			promise
				.then(function(reviewTitles) {
					return ProductResource.queryAllByReviewTitles(reviewTitles);
				})
				.then(function(products) {
					var list;
					list = products.map(function(el) {
						return el.brandName + ' - ' + el.productName;
					}).sort(function(e1, e2) {
						return e1 < e2;
					});
					if (list.length > 0) {
						list = list.join('\n');
					} else {
						list = 'None';
					}
					alert(list);
				})
				.catch(function(msg) {
					alert('Error:', msg);
				});

		};

		// var today=new Date();
		// today.setHour(0);
		// today.setHour(0);

		var q1 = new QualityCheckRunner({
			api: RawTextReview,
			apiName: 'RawTextReview',
			isNullValue: ['pubDate', 'country', 'channel', 'title', 'subtitle','translation'],
			isLongerThan: [{
				fieldName: 'authorName',
				maxLength: 113
			}],
			isGreaterThan: [{
				fieldName: 'pubDate',
				upperBound: 'ISODate(\'' + new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), 14, 0).toISOString() + '\')'
			}],
			isLessThan: [{
				fieldName: 'pubDate',
				lowerBound: 'ISODate(\'' + new Date(1995, 1, 1).toISOString() + '\')'
			}],
			isType: [{
				fieldName: 'pubDate',
				expectedType: 'Date'
			}]
		});
		var q2 = new QualityCheckRunner({
			api: TextReview,
			apiName: 'TextReview',
			qualityCheckRunnersSettings: $scope.qualityCheckRunnersSettings,
			isNullValue: ['review.pubDate', 'review.country', 'review.channel', 'review.title', 'review.subtitle','review.translation'],
			isLongerThan: [{
				fieldName: 'review.authorName',
				maxLength: 113
			}],
			isGreaterThan: [{
				fieldName: 'review.pubDate',
				upperBound: 'ISODate(\'' + new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), 14, 0).toISOString() + '\')'
			}],
			isLessThan: [{
				fieldName: 'review.pubDate',
				lowerBound: 'ISODate(\'' + new Date(1995, 1, 1).toISOString() + '\')'
			}],
			isType: [{
				fieldName: 'review.pubDate',
				expectedType: 'Date'
			}]
		});
		var loadData = function() {

			if ($scope.currentQueryForAnalyzedReviews===null && $scope.currentQueryForRawTextReviews===null){
				return;
			}


			$scope.isQualityCheckUpdating = true;

			$q.all([q1.run(), q2.run()])
				.then(function(res) {
					$log.info('>>> Result - RawReviews', res[0]);
					$scope.dataFromQualityCheckOnRawTextReviews = res[0];

					$log.info('>>> Result - Analyzed Reviews', res[1]);
					$scope.dataFromQualityCheckOnAnalyzedReviews = res[1];

				})
				.catch(function(msg) {
					return alert('Error: ' + msg);
				})
				.finally(function() {
					$scope.isQualityCheckUpdating = false;
				});

		};

		loadData();



	};

angular.module('app')
  .controller('QualitycheckController', QualitycheckController)
  .config(function routes($stateProvider) {
    $stateProvider
      .state('qualitycheck', {
        url: '/qualitycheck',
        template: require('./qualitycheck.html'),
        controller: 'QualitycheckController',
        controllerAs: 'qualityCheck'
      });
  });
