WidgetHelperSrvc.js

angular.module('homepage').
// Do widgets related calculations here and update the DataStoreSrvc 'DataStore.widgets'
factory('WidgetHelperSrvc', function (FoodNutritionSrvc, TemplateTimelineService) {
	// Store the original data templates copy here (READ ONLY)
	var DataStore = {
		mood: {
			templates: []
		},
		money: {
			templates: []
		},
		food: {
			templates: []
		},
		fitness: {
			templates: []
		}
	};

	var widgets 	= {};
	widgets.mood    = new MoodWidgetsData();
	widgets.money   = new MoneyWidgetsData();
	widgets.food    = new FoodWidgetsData();
	widgets.fitness = new FitnessWidgetsData();

	function MoodWidgetsData() {
		return {
			list: []
		};
	}

	function MoneyWidgetsData() {
		return {
			received: 0,
			spent: 0,
			lent: 0,
			borrowed: 0,
			remaining: 0
		};
	}

	function FoodWidgetsData() {
		return {
			calories: {
				required: 0,
				consumed: 0,
				message: 'No food info recorded'
			}
		};
	}

	function FitnessWidgetsData() {
		return {
			workouts: [],
			message: ''
		};
	}

	function resetWidgets(type) {
		type = type ? type : '';

		switch(type) {
			case 'MOOD':
				widgets.mood 	= new MoodWidgetsData();
				break;
			case 'MNEY':
				widgets.money 	= new MoneyWidgetsData();
				break;
			case 'FOOD':
				widgets.food 	= new FoodWidgetsData();
				break;
			case 'HLTH':
				widgets.fitness	= new FitnessWidgetsData();
				break;
			default:
				widgets.mood 	= new MoodWidgetsData();
				widgets.money 	= new MoneyWidgetsData();
				widgets.food 	= new FoodWidgetsData();
				widgets.fitness = new FitnessWidgetsData();
		}
	}

	function updateDataStore(data) {
		if(data.type == 'FOOD') {
			DataStore.food.templates.push(data);
		}
		else if(data.type == 'MOOD') {
			DataStore.mood.templates.push(data);
		}
		else if(data.type == 'MNEY') {
			DataStore.money.templates.push(data);
		}
		else if(data.type == 'HLTH') {
			DataStore.fitness.templates.push(data);
		}
	}

	function updateWidgetData(data) {
		if(data.type == 'FOOD') {
			updateFoodWidget(data);
		}
		else if(data.type == 'MOOD') {
			updateMoodWidget(data);
		}
		else if(data.type == 'MNEY') {
			updateMoneyWidget(data);
		}
		else if(data.type == 'HLTH') {
			updateFitnessWidget(data);
		}
	}

	/**
	 * Calculate total calories consumed throughout a given day
	 * @param  {Object} data Object representing one snippet
	 * @return {Object}      Returns object with attributes used on UI
	 */
	function updateFoodWidget(data) {
		resetWidgets('FOOD');

		var hasUnknown  = false; // If any food calories is unknown
		var totalcalories 	= 0;
		var required 	= 2500;
		var message 	= '';
		var foods 		= TemplateTimelineService.getItemsByDate(DataStore.food.templates);
		for(var index in foods) {
			var food = foods[index];
			for(var listindex in food.data.list) {
				var fooditem = food.data.list[listindex];
				if(fooditem.count) {
					var value = parseInt(fooditem.count);
					if(typeof value == 'number') {
						totalcalories += value;
					}
				}
				else if(fooditem.foodtext) {
					var nutritionInfo = FoodNutritionSrvc.getNutritionInfo(fooditem.foodtext, fooditem.mealtype, fooditem.quantity, fooditem.qtytype);
					var calories = parseInt(nutritionInfo.calories);
					if(calories > 0) {
						totalcalories += calories;
					}
					else {
						hasUnknown = true;
					}
				}
			}
		}

		var diff = required - totalcalories;
		if(diff > 0) {
			message = 'Going good';
		}
		else {
			if(Math.abs(diff) < 1000) {
				message = 'Little overloaded';
			}
			else {
				message = 'Workout needed';
			}
		}
		widgets.food.calories.message   = message;
		widgets.food.calories.consumed  = hasUnknown ? totalcalories + ' + X Cal' : totalcalories;
		widgets.food.calories.required  = required;
	}

	function updateMoodWidget(data) {
		resetWidgets('MOOD');
		var moodLevel = parseInt(data.data.level);
		moodLevel = typeof moodLevel == 'number' ? moodLevel : 0;
		widgets.mood.list.push({level: moodLevel, timestamp: data.timestamp});
	}

	function updateMoneyWidget(data) {
		resetWidgets('MNEY');

		for(var index in DataStore.money.templates) {
			var template = DataStore.money.templates[index];
			var amount = parseInt(template.data.amount);
			amount = amount && amount > 0 ? amount : 0;

			if(template.data.financetype == 'PAID') {
				if(template.data.whomobj || template.data.whom) {
					widgets.money.lent += amount;
				}
				else {
					widgets.money.spent += amount;
				}
			}
			if(template.data.financetype == 'RCVD') {
				if(template.data.whomobj || template.data.whom) {
					widgets.money.borrowed += amount;
				}
				else {
					widgets.money.received += amount;
				}
			}
		}

		var remaining = (widgets.money.received + widgets.money.borrowed) -
			(widgets.money.lent + widgets.money.spent);
		widgets.money.remaining = remaining;
	}

	/**
	 * Build list of info to be shown on fitness widget
	 * @param  {Object} data Object representing one snippet
	 * @return {Object}      Returns object with attributes used on UI
	 */
	function updateFitnessWidget(data) {
		for(var index in data.data.list) {
			var workout = data.data.list[index];
			widgets.fitness.workouts.push(workout);
		}

		if(widgets.fitness.workouts.length > 0) {
			widgets.fitness.message = "Keep burning calories";
		}
	}

	return {
		/**
		 * Initialize all the data using the list of templates received
		 */
		initialize: function (templates, type) {
			// Reinitialize all data before processing all items
			resetWidgets(type);

			// Process templates only applicable for today
			templates = TemplateTimelineService.getItemsByDate(templates);

			for(var index in templates) {
				var template = templates[index];
				updateWidgetData(template);
			}
		},
		getWidgetsByDate: function (templates) {
			this.initialize(DataStore.mood.templates, 'MOOD');
			this.initialize(DataStore.money.templates, 'MNEY');
			this.initialize(DataStore.food.templates, 'FOOD');
			this.initialize(DataStore.fitness.templates, 'HLTH');
			return widgets;
		},
		/**
		 * Return the widget object
		 */
		getWidgetsData: function () {
		 	return widgets;
		},
		/*
		 * Update widgets data based by performing calculations as per the template type passed
		 */
		update: function (template) {
		 	updateDataStore(template);
		 	updateWidgetData(template);
		 	return widgets;
		},
		/**
		 * Reset data store
		 */
		resetAll: function () {
			DataStore.mood.templates.length = 0;
			DataStore.money.templates.length = 0;
			DataStore.food.templates.length = 0;
			DataStore.fitness.templates.length = 0;
		}
	 };
	});