define([
	],
	function() {
		var hostController = function(
			$scope,
			$q,
			$timeout,
			update,
			devices,
			mounts,
			CENTRAL_API_URL,
			RING_TYPES
		) {
			var self = this;
			this.isArray = _.isArray;
			this.isUndefined = _.isUndefined;
			var selections = [];

			// DEVICE CONTROLS
			this.processAction = function(selection, group) {
				var updates = _.map(selection.asArray(), function(device) {
					var req;

					updateURL = ([
						// CENTRAL_API_URL,
						// 'swift',
						'/swift',
						group.type,
						$scope.data.rings[group.type].uuid[device.uuid].id
					]).join('/');

					switch(selection.action) {
						case 'SAVE':
							req = update.setEndpoint(updateURL)
								.setParameters({
									'weight': device.weight.new
								})
								.put({})
							break;
						case 'DELETE':
							req = update.setEndpoint(updateURL)
								.setParameters({
									'instant': 'true'
								})
								.delete({})
							break;
					}

					//ugh this is disgusting but this is how we hack around $q's lack of a allSettled() fn
					return req.then(
						function(result) {
							return {
								success: true
							}
						},
						function(error) {
							return {
								success: false
							}
						});
				})

				$q.all(updates).then(function(results) {
					selection.result = {
						total: results.length
					}

					if(_.every(results, 'success')) {
						selection.status = 'SUCCESS';
						selection.result.succeeded = results.length;
					} else {
						selection.status = 'ERROR';
						selection.result.succeeded = _.filter(results, 'success').length;
					}

					$scope.data.refreshRedis();

					$timeout(function() {
						selection.status = 'NORMAL'
						selection.result = undefined
					}, 1000 * 3)
				});
			}
			this.leaveEdit = function(mount) {
				mount.edit = false;
			}
			this.cancel = function(mount) {
				mount.status = 'NORMAL';
			}
			this.initWeights = function(device, group) {
				if(!_.has(device, 'weight')) {
					if(_.isUndefined($scope.data.redis.weight_targets[group.type][$scope.data.rings[group.type].uuid[device.uuid].id])) {
						targetWeight = $scope.data.rings[group.type].uuid[device.uuid].weight;
					} else {
						targetWeight = parseInt($scope.data.redis.weight_targets[group.type][$scope.data.rings[group.type].uuid[device.uuid].id], 10);
					}

					device.weight = {
						old: $scope.data.rings[group.type].uuid[device.uuid].weight,
						new: targetWeight,
					}
				}
			}

			// DEVICE SORTING
			this.getStatus = function(device) {
				try {
					return self.isPartOfRing(device, device) ? 1 : 2
				}
				catch(e) {
					return true
				}
			}

			// DEVICE STATUS
			this.isHealthy = function(device, group) {
				if(_.includes(RING_TYPES, group.type)) {
					if(_.isUndefined($scope.data.health[group.type].servers[device.ip])) {
						return false;
					} else {
						return _.isUndefined($scope.data.health[group.type].servers[device.ip].unhealthy_devices[device.uuid]);
					}
				}

				return true
			}
			this.isReweighting = function(device, group) {
				return self.isPartOfRing(device, group) &&
					!_.isUndefined($scope.data.redis.weight_targets[group.type][$scope.data.rings[group.type].uuid[device.uuid].id])
			}
			this.isBeingAdded = function(device, group) {
				if(_.includes(RING_TYPES, group.type)) {
					return _.find($scope.data.redis.add_devices[group.type], {'host': device.hostname, 'drive': device.path.substr(5)});
				}

				return false
			}
			this.isPartOfRing = function(device, group) {
				if(_.includes(RING_TYPES, group.type)) {
					return !_.isUndefined($scope.data.rings[group.type].uuid[device.uuid])
				}

				return false
			}

			// SELECTIONS
			this.select = function(idx) {
				if(selections.length === 2) {
					self.deselect()
				} else {
					selections.push(idx);
					var min = _.min(selections);
					var max = _.max(selections);
					var mounts = _.flatten(self.mounts);

					mounts.splice(min, max - min + 1, _.slice(mounts, min, max + 1))
					self.mounts = mounts
					self.selected = _.min(selections)
				}
			}
			this.deselect = function() {
				self.mounts = _.flatten(self.mounts);
				selections = [];
				self.selected = undefined
			}
			this.selectable = function() {
				return selections.length < 2;
			}

			this.init = function(host, group) {
				host.loading = true;

				var mountsURL = ([
					'http:/',
					host.ip,
					'uuids'
				]).join('/');

				$q.all([
					mounts.setEndpoint(mountsURL)
						.get(),
					$scope.data.initialized
				]).then(function(results) {
					var mounts = results[0].data

					if(_.includes(RING_TYPES, group.type)) {
						devices = _.chain($scope.data.rings[group.type].uuid)
							.filter(function(device) {
								return device.ip === host.ip.substr(0, host.ip.length - 5)
							})
							.value()
					} else {
						devices = []
					}

					var pathMap = _.chain(mounts)
						.map(function(obj, path) {
							obj.path = path;
							return obj;
						})
						.indexBy('uuid')
						.value();

					self.mounts = _.chain(devices)
						.filter(function(device) {
							return pathMap[device.device];
						})
						.map(function(device) {
							return {
								path: pathMap[device.device].path,
								uuid: device.device,
								id: device.id
							}
						})
						.concat(_.map(mounts, function(mount, path) {
							mount.path = path;
							return mount
						}))
						.uniq(false, 'uuid')
						.map(function(device) {
							//some initialization
							var targetWeight;
							device.type = group.type;
							device.ip = host.ip;
							device.hostname = host.name;

							return device;
						})
						.sortByOrder([
							self.getStatus,
							'path'
						],
						[
							'desc',
							'asc',
						])
						.value()

					host.loading = false;
				})
			}
		}

		return hostController;
	}
)