define [
	"base"
], (App) ->

	App.controller "ProjectPageController", ($scope, $modal, $q, $window, queuedHttp, event_tracking, $timeout, localStorage) ->
		$scope.projects = window.data.projects
		$scope.tags = window.data.tags
		$scope.notifications = window.data.notifications
		$scope.allSelected = false
		$scope.selectedProjects = []
		$scope.isArchiveableProjectSelected = false
		$scope.filter = "all"
		$scope.predicate = "lastUpdated"
		$scope.nUntagged = 0
		$scope.reverse = true
		$scope.searchText = 
			value : ""

		$timeout () ->
			recalculateProjectListHeight()
		, 10

		$scope.$watch((
			() -> $scope.projects.filter((project) -> (!project.tags? or project.tags.length == 0) and !project.archived).length
		), (newVal) -> $scope.nUntagged = newVal)

		storedUIOpts = JSON.parse(localStorage("project_list"))

		recalculateProjectListHeight = () ->
			$projListCard = $(".project-list-card")
			topOffset = $projListCard.offset()?.top
			cardPadding = $projListCard.outerHeight() - $projListCard.height()
			bottomOffset = $("footer").outerHeight()
			height = $window.innerHeight - topOffset - bottomOffset - cardPadding
			$scope.projectListHeight = height

		angular.element($window).bind "resize", () ->
			recalculateProjectListHeight()
			$scope.$apply()
			
		# Allow tags to be accessed on projects as well
		projectsById = {}
		for project in $scope.projects
			projectsById[project.id] = project

		for tag in $scope.tags
			for project_id in tag.project_ids or []
				project = projectsById[project_id]
				if project?
					project.tags ||= []
					project.tags.push tag

		markTagAsSelected = (id) ->
			for tag in $scope.tags
				if tag._id == id
					tag.selected = true
				else
					tag.selected = false
		
		$scope.changePredicate = (newPredicate)->
			if $scope.predicate == newPredicate
				$scope.reverse = !$scope.reverse
			$scope.predicate = newPredicate

		$scope.getSortIconClass = (column)->
			if column == $scope.predicate and $scope.reverse
				return "fa-caret-down"
			else if column == $scope.predicate and !$scope.reverse
				return "fa-caret-up"
			else
				return ""

		$scope.searchProjects = ->
			event_tracking.send 'project-list-page-interaction', 'project-search', 'keydown'
			$scope.updateVisibleProjects()

		$scope.clearSearchText = () ->
			$scope.searchText.value = ""
			$scope.filter = "all"
			$scope.$emit "search:clear"
			$scope.updateVisibleProjects()

		$scope.setFilter = (filter) ->
			$scope.filter = filter
			$scope.updateVisibleProjects()

		$scope.updateSelectedProjects = () ->
			$scope.selectedProjects = $scope.projects.filter (project) -> project.selected
			$scope.isArchiveableProjectSelected = $scope.selectedProjects.some (project) ->
				window.user_id == project.owner._id

		$scope.getSelectedProjects = () ->
			$scope.selectedProjects

		$scope.getSelectedProjectIds = () ->
			$scope.selectedProjects.map (project) -> project.id

		$scope.getFirstSelectedProject = () ->
			$scope.selectedProjects[0]

		$scope.updateVisibleProjects = () ->
			$scope.visibleProjects = []
			selectedTag = $scope.getSelectedTag()
			for project in $scope.projects
				visible = true
				# Only show if it matches any search text
				if $scope.searchText.value? and $scope.searchText.value != ""
					if project.name.toLowerCase().indexOf($scope.searchText.value.toLowerCase()) == -1
						visible = false
				# Only show if it matches the selected tag
				if $scope.filter == "tag" and selectedTag? and project.id not in selectedTag.project_ids
					visible = false

				# Hide tagged projects if we only want to see the uncategorized ones
				if $scope.filter == "untagged" and project.tags?.length > 0
					visible = false

				# Hide projects we own if we only want to see shared projects
				if $scope.filter == "shared" and project.accessLevel == "owner"
					visible = false

				# Hide projects from V1 if we only want to see shared projects
				if $scope.filter == "shared" and project.isV1Project
					visible = false

				# Hide projects we don't own if we only want to see owned projects
				if $scope.filter == "owned" and project.accessLevel != "owner"
					visible = false

				if $scope.filter == "archived"
					# Only show archived projects
					if !project.archived
						visible = false
				else
					# Only show non-archived projects
					if project.archived
						visible = false

				if $scope.filter == "v1" and !project.isV1Project
					visible = false

				if visible
					$scope.visibleProjects.push project
				else
					# We don't want hidden selections
					project.selected = false

			localStorage("project_list", JSON.stringify({ 
				filter: $scope.filter,
				selectedTagId: selectedTag?._id
			}))
			$scope.updateSelectedProjects()

		$scope.getSelectedTag = () ->
			for tag in $scope.tags
				return tag if tag.selected
			return null

		$scope._removeProjectIdsFromTagArray = (tag, remove_project_ids) ->
			# Remove project_id from tag.project_ids
			remaining_project_ids = []
			removed_project_ids = []
			for project_id in tag.project_ids
				if project_id not in remove_project_ids
					remaining_project_ids.push project_id
				else
					removed_project_ids.push project_id
			tag.project_ids = remaining_project_ids
			return removed_project_ids

		$scope._removeProjectFromList = (project) ->
			index = $scope.projects.indexOf(project)
			if index > -1
				$scope.projects.splice(index, 1)

		$scope.removeSelectedProjectsFromTag = (tag) ->
			tag.showWhenEmpty = true

			selected_project_ids = $scope.getSelectedProjectIds()
			selected_projects = $scope.getSelectedProjects()

			removed_project_ids = $scope._removeProjectIdsFromTagArray(tag, selected_project_ids)

			# Remove tag from project.tags
			remaining_tags = []
			for project in selected_projects
				project.tags ||= []
				index = project.tags.indexOf tag
				if index > -1
					project.tags.splice(index, 1)

			for project_id in removed_project_ids
				queuedHttp({
					method: "DELETE"
					url: "/tag/#{tag._id}/project/#{project_id}"
					headers:
						"X-CSRF-Token": window.csrfToken
				})

			# If we're filtering by this tag then we need to remove
			# the projects from view
			$scope.updateVisibleProjects()

		$scope.removeProjectFromTag = (project, tag) ->
			tag.showWhenEmpty = true

			project.tags ||= []
			index = project.tags.indexOf tag

			if index > -1
				$scope._removeProjectIdsFromTagArray(tag, [ project.id ])
				project.tags.splice(index, 1)
				queuedHttp({
					method: "DELETE"
					url: "/tag/#{tag._id}/project/#{project.id}"
					headers:
						"X-CSRF-Token": window.csrfToken
				})
				$scope.updateVisibleProjects()

		$scope.addSelectedProjectsToTag = (tag) ->
			selected_projects = $scope.getSelectedProjects()
			event_tracking.send 'project-list-page-interaction', 'project action', 'addSelectedProjectsToTag'

			# Add project_ids into tag.project_ids
			added_project_ids = []
			for project_id in $scope.getSelectedProjectIds()
				unless project_id in tag.project_ids
					tag.project_ids.push project_id
					added_project_ids.push project_id

			# Add tag into each project.tags
			for project in selected_projects
				project.tags ||= []
				unless tag in project.tags
					project.tags.push tag

			for project_id in added_project_ids
				queuedHttp.post "/tag/#{tag._id}/project/#{project_id}", {
					_csrf: window.csrfToken
				}

		$scope.createTag = (name) ->
			return tag

		$scope.openNewTagModal = (e) ->
			modalInstance = $modal.open(
				templateUrl: "newTagModalTemplate"
				controller: "NewTagModalController"
			)

			modalInstance.result.then(
				(tag) ->
					$scope.tags.push tag
					$scope.addSelectedProjectsToTag(tag)
			)

		$scope.createProject = (name, template = "none") ->
			return queuedHttp
				.post("/project/new", {
					_csrf: window.csrfToken
					projectName: name
					template: template
				})
				.then((response) ->
					{ data } = response
					$scope.projects.push {
						name: name
						_id: data.project_id
						accessLevel: "owner"
						# TODO: Check access level if correct after adding it in
						# to the rest of the app
					}
					$scope.updateVisibleProjects()
				)

		$scope.openCreateProjectModal = (template = "none") ->
			event_tracking.send 'project-list-page-interaction', 'new-project', template
			modalInstance = $modal.open(
				templateUrl: "newProjectModalTemplate"
				controller: "NewProjectModalController"
				resolve:
					template: () -> template
				scope: $scope
			)

			modalInstance.result.then (project_id) ->
				window.location = "/project/#{project_id}"

		$scope.renameProject = (project, newName) ->
			return queuedHttp.post "/project/#{project.id}/rename", {
				newProjectName: newName,
				_csrf: window.csrfToken
			}
				.then () ->
					project.name = newName

		$scope.openRenameProjectModal = () ->
			project = $scope.getFirstSelectedProject()
			return if !project? or project.accessLevel != "owner"
			event_tracking.send 'project-list-page-interaction', 'project action', 'Rename'
			modalInstance = $modal.open(
				templateUrl: "renameProjectModalTemplate"
				controller: "RenameProjectModalController"
				resolve:
					project: () -> project
				scope: $scope
			)

		$scope.cloneProject = (project, cloneName) ->
			event_tracking.send 'project-list-page-interaction', 'project action', 'Clone'
			queuedHttp
				.post("/project/#{project.id}/clone", {
					_csrf: window.csrfToken
					projectName: cloneName
				})
				.then((response) ->
					{ data } = response
					$scope.projects.push {
						name: cloneName
						id: data.project_id
						accessLevel: "owner"
						owner: {
							_id: user_id
						}
						# TODO: Check access level if correct after adding it in
						# to the rest of the app
					}
					$scope.updateVisibleProjects()
				)

		$scope.openCloneProjectModal = () ->
			project = $scope.getFirstSelectedProject()
			return if !project?

			modalInstance = $modal.open(
				templateUrl: "cloneProjectModalTemplate"
				controller: "CloneProjectModalController"
				resolve:
					project: () -> project
				scope: $scope
			)

		$scope.openArchiveProjectsModal = () ->
			modalInstance = $modal.open(
				templateUrl: "deleteProjectsModalTemplate"
				controller: "DeleteProjectsModalController"
				resolve:
					projects: () -> $scope.getSelectedProjects()
			)
			event_tracking.send 'project-list-page-interaction', 'project action', 'Delete'
			modalInstance.result.then () ->
				$scope.archiveOrLeaveSelectedProjects()

		$scope.archiveOrLeaveSelectedProjects = () ->
			$scope.archiveOrLeaveProjects($scope.getSelectedProjects())

		$scope.archiveOrLeaveProjects = (projects) ->
			projectIds = projects.map (p) -> p.id
			# Remove project from any tags
			for tag in $scope.tags
				$scope._removeProjectIdsFromTagArray(tag, projectIds)

			for project in projects
				project.tags = []
				if project.accessLevel == "owner"
					project.archived = true
					queuedHttp {
						method: "DELETE"
						url: "/project/#{project.id}"
						headers:
							"X-CSRF-Token": window.csrfToken
					}
				else
					$scope._removeProjectFromList project

					queuedHttp {
						method: "POST"
						url: "/project/#{project.id}/leave"
						headers:
							"X-CSRF-Token": window.csrfToken
					}

			$scope.updateVisibleProjects()


		$scope.openDeleteProjectsModal = () ->
			modalInstance = $modal.open(
				templateUrl: "deleteProjectsModalTemplate"
				controller: "DeleteProjectsModalController"
				resolve:
					projects: () -> $scope.getSelectedProjects()
			)

			modalInstance.result.then () ->
				$scope.deleteSelectedProjects()

		$scope.deleteSelectedProjects = () ->
			selected_projects = $scope.getSelectedProjects()
			selected_project_ids = $scope.getSelectedProjectIds()

			# Remove projects from array
			for project in selected_projects
				$scope._removeProjectFromList project

			# Remove project from any tags
			for tag in $scope.tags
				$scope._removeProjectIdsFromTagArray(tag, selected_project_ids)

			for project_id in selected_project_ids
				queuedHttp {
					method: "DELETE"
					url: "/project/#{project_id}?forever=true"
					headers:
						"X-CSRF-Token": window.csrfToken
				}

			$scope.updateVisibleProjects()

		$scope.restoreSelectedProjects = () ->
			$scope.restoreProjects($scope.getSelectedProjects())

		$scope.restoreProjects = (projects) ->
			projectIds = projects.map (p) -> p.id
			for project in projects
				project.archived = false

			for projectId in projectIds
				queuedHttp {
					method: "POST"
					url: "/project/#{projectId}/restore"
					headers:
						"X-CSRF-Token": window.csrfToken
				}

			$scope.updateVisibleProjects()

		$scope.openUploadProjectModal = () ->
			modalInstance = $modal.open(
				templateUrl: "uploadProjectModalTemplate"
				controller: "UploadProjectModalController"
			)

		$scope.downloadSelectedProjects = () ->
			$scope.downloadProjectsById($scope.getSelectedProjectIds())

		$scope.downloadProjectsById = (projectIds) ->
			event_tracking.send 'project-list-page-interaction', 'project action', 'Download Zip'
			if projectIds.length > 1
				path = "/project/download/zip?project_ids=#{projectIds.join(',')}"
			else
				path = "/project/#{projectIds[0]}/download/zip"
			window.location = path

		$scope.openV1ImportModal = (project) ->
			$modal.open(
				templateUrl: 'v1ImportModalTemplate'
				controller: 'V1ImportModalController'
				size: 'lg'
				windowClass: 'v1-import-modal'
				resolve:
					project: () -> project
			)
			
		if storedUIOpts?.filter?
			if storedUIOpts.filter == "tag" and storedUIOpts.selectedTagId?
				markTagAsSelected(storedUIOpts.selectedTagId)
			$scope.setFilter(storedUIOpts.filter)
		else
			$scope.updateVisibleProjects()

	App.controller "ProjectListItemController", ($scope) ->

		$scope.shouldDisableCheckbox = (project) ->
			$scope.filter == 'archived' && project.accessLevel != 'owner'

		$scope.projectLink = (project) ->
			if project.accessLevel == 'readAndWrite' and project.source == 'token'
				"/#{project.tokens.readAndWrite}"
			else if project.accessLevel == 'readOnly' and project.source == 'token'
				"/read/#{project.tokens.readOnly}"
			else
				"/project/#{project.id}"

		$scope.isLinkSharingProject = (project) ->
			return project.source == 'token'

		$scope.ownerName = () ->
			if $scope.project.accessLevel == "owner"
				return "You"
			else if $scope.project.owner?
				return [$scope.project.owner.first_name, $scope.project.owner.last_name].filter((n) -> n?).join(" ")
			else
				return "None"

		$scope.isOwner = () ->
			window.user_id == $scope.project.owner._id

		$scope.$watch "project.selected", (value) ->
			if value?
				$scope.updateSelectedProjects()

		$scope.clone = (e) ->
			e.stopPropagation()
			$scope.cloneProject($scope.project, "#{$scope.project.name} (Copy)")

		$scope.download = (e) ->
			e.stopPropagation()
			$scope.downloadProjectsById([$scope.project.id])

		$scope.archiveOrLeave = (e) ->
			e.stopPropagation()
			$scope.archiveOrLeaveProjects([$scope.project])

		$scope.restore = (e) ->
			e.stopPropagation()
			$scope.restoreProjects([$scope.project])
