app.service('deployments', ['$q', '$http', '$interval', '$cookies', '$state', 'config', 'repos', function($q, $http, $interval, $cookies, $state, config, repos) {
	var that = this

	this.set_repo = function(owner, repo) {
		var deferred = $q.defer()

		if (owner == that.owner && repo == that.repo) {
			deferred.resolve()
			return deferred.promise
		}

		that.owner = owner
		that.repo = repo
		that.environments = []
		that.deploys = {}
		that.statuses = {}
		that.watched_deploys = []
		that.watchers = {}

		if (repos.settings != null && repos.settings.deploy != null) {
			that.environments = Object.keys(repos.settings.deploy.environments)
		}

		that.load_recent_deploys()
			.then(that.load_deployment_statuses)
			.then(function() {
				deferred.resolve()
			})

		return deferred.promise
	}

	this.create = function(branch, ref, environment, description) {
		data = $.param({
			owner: that.owner,
			repo: that.repo,
			ref: ref,
			branch: branch,
			environment: environment,
			description: description
		})

		c = {
			headers: {
				'Content-Type': 'application/x-www-form-urlencoded'
			}
		}

		$http.post(config.skadi_host+"/v1/deployments", data, c)
			.success(function(deployment) {
				that.deploys[deployment.environment].unshift(deployment)
				that.start_watching(deployment)
				$state.go('repo.deploy', {id: deployment.id})
			})
	}

	this.get = function(id) {
		var deferred = $q.defer();

		for (var env in that.deploys) {
			that.deploys[env].forEach(function(deploy) {
				if (deploy.id == id) {
					deferred.resolve(deploy)
				}
			})
		}

		// TODO: if not found, hit skadi service to load single deploy

		return deferred.promise
	}

	// start_watching starts an $interval which queries the status of a deployment until it either succeeds
	// or fails.
	this.start_watching = function(deploy) {
		if (that.watched_deploys.indexOf(deploy.id) == -1) {
			that.watched_deploys.push(deploy.id)

			that.watchers[deploy.id] = $interval(function() {
				that.load_deployment_status_for_deploy(deploy, false)
					.then(function() {
						if (that.statuses[deploy.id].state == "success" || that.statuses[deploy.id].state == "failure") {
							if ($interval.cancel(that.watchers[deploy.id])) {
								that.watched_deploys.splice(that.watched_deploys.indexOf(deploy.id), 1)
								delete that.watchers[deploy.id]
							}
						}
					})
			}, 10000)
		}
	}

	this.load_recent_deploys = function() {
		var promises = []

		that.environments.forEach(function(environment) {
			p = that.get_deploys_for_env(environment)
				.then(function(deployments) {
					var env = environment
					that.deploys[env] = deployments
				})

			promises.push(p)
		})

		return $q.all(promises)
	}

	this.get_deploys_for_env = function(environment) {
		var deferred = $q.defer()

		$http.get(config.skadi_host+"/v1/deployments?owner="+that.owner+"&repo="+that.repo+"&environment="+environment)
			.success(function(deployments) {
				deferred.resolve(deployments)
			})

		return deferred.promise
	}

	this.load_deployment_statuses = function() {
		var promises = []

		that.environments.forEach(function(environment) {
			var env = environment

			that.deploys[env].forEach(function(deploy) {
				p = that.load_deployment_status_for_deploy(deploy, true)
				promises.push(p)
			})
		})

		return $q.all(promises)
	}

	this.load_deployment_status_for_deploy = function(deploy, watch) {
		return $http.get(config.skadi_host+"/v1/deployments/"+deploy.id+"/status")
			.success(function(status) {
				that.statuses[deploy.id] = status
				if (watch) {
					if (status.state == "pending" || status.state == "unknown") {
						that.start_watching(deploy)
					}
				}
			})
	}

	this.deploy_percentage = function(deploy_id) {
		if (deploy_id && that.statuses[deploy_id]) {
			return that.statuses[deploy_id].percent
		}
		
		return 0
	}

	this.get_log_output = function(deploy_id) {
		var deferred = $q.defer()

		$http.get(config.skadi_host+"/v1/deployments/"+deploy_id+"/log")
			.success(function(log) {
				deferred.resolve(log.output)
			})		

		return deferred.promise
	}
}]);
