 						positions.push row: row, column: result.index
 						words.push(word)
 			return words: words, positions: positions
-
-		apiRequest: (endpoint, data, callback = (error, result) ->)->
-			data.token = window.user.id
-			data._csrf = window.csrfToken
-			# use angular timeout option to cancel request if doc is changed
-			requestHandler = @$q.defer()
-			options = {timeout: requestHandler.promise}
-			httpRequest = @$http.post("/spelling" + endpoint, data, options)
-			.then (response) =>
-				callback(null, response.data)
-			.catch (response) =>
-				callback(new Error('api failure'))
-			# provide a method to cancel the request
-			abortRequest = () ->
-				requestHandler.resolve()
-			return { abort: abortRequest }
 
 		blacklistedCommandRegex: ///
 			\\                    # initial backslash

define [
	"ide/editor/directives/aceEditor/spell-check/HighlightedWordManager"
	"ace/ace"
], (HighlightedWordManager) ->
	Range = ace.require("ace/range").Range

	class SpellCheckManager
		constructor: (@$scope, @editor, @element, @cache, @$http, @$q) ->
			$(document.body).append @element.find(".spell-check-menu")
			@inProgressRequest = null
			@updatedLines = []
			@highlightedWordManager = new HighlightedWordManager(@editor)

			@$scope.$watch "spellCheckLanguage", (language, oldLanguage) =>
				if language != oldLanguage and oldLanguage?
					@runFullCheck()

			onChange = (e) =>
				@runCheckOnChange(e)
				
			onScroll = () =>
				@closeContextMenu()

			@editor.on "changeSession", (e) =>
				@highlightedWordManager.reset()
				if @inProgressRequest?
					@inProgressRequest.abort()

				if @$scope.spellCheckEnabled and @$scope.spellCheckLanguage and @$scope.spellCheckLanguage != ""
					@runSpellCheckSoon(200)

				e.oldSession?.getDocument().off "change", onChange
				e.session.getDocument().on "change", onChange
				
				e.oldSession?.off "changeScrollTop", onScroll
				e.session.on "changeScrollTop", onScroll

			@$scope.spellingMenu = {left: '0px', top: '0px'}

			@editor.on "nativecontextmenu", (e) =>
				e.domEvent.stopPropagation();
				@closeContextMenu(e.domEvent)
				@openContextMenu(e.domEvent)

			$(document).on "click", (e) =>
				if e.which != 3 # Ignore if this was a right click
					@closeContextMenu(e)
				return true

			@$scope.replaceWord = (highlight, suggestion) =>
				@replaceWord(highlight, suggestion)

			@$scope.learnWord = (highlight) =>
				@learnWord(highlight)

		runFullCheck: () ->
			@highlightedWordManager.clearRows()
			if @$scope.spellCheckLanguage and @$scope.spellCheckLanguage != ""
				@runSpellCheck()

		runCheckOnChange: (e) ->
			if @$scope.spellCheckLanguage and @$scope.spellCheckLanguage != ""
				@highlightedWordManager.applyChange(e)
				@markLinesAsUpdated(e)
				@runSpellCheckSoon()

		openContextMenu: (e) ->
			position = @editor.renderer.screenToTextCoordinates(e.clientX, e.clientY)
			highlight = @highlightedWordManager.findHighlightWithinRange
				start: position
				end:   position

			@$scope.$apply () =>
				@$scope.spellingMenu.highlight = highlight

			if highlight
				e.stopPropagation()
				e.preventDefault()

				@editor.getSession().getSelection().setSelectionRange(
					new Range(
						highlight.row, highlight.column
						highlight.row, highlight.column + highlight.word.length
					)
				)

				@$scope.$apply () =>
					@$scope.spellingMenu.open = true
					@$scope.spellingMenu.left = e.clientX + 'px'
					@$scope.spellingMenu.top = e.clientY + 'px'
				return false

		closeContextMenu: (e) ->
			# this is triggered on scroll, so for performance only apply
			# setting when it changes
			if @$scope?.spellingMenu?.open != false
				@$scope.$apply () =>
					@$scope.spellingMenu.open = false

		replaceWord: (highlight, text) ->
			@editor.getSession().replace(new Range(
				highlight.row, highlight.column,
				highlight.row, highlight.column + highlight.word.length
			), text)

		learnWord: (highlight) ->
			@apiRequest "/learn", word: highlight.word
			@highlightedWordManager.removeWord highlight.word
			language = @$scope.spellCheckLanguage
			@cache?.put("#{language}:#{highlight.word}", true)

		getHighlightedWordAtCursor: () ->
			cursor = @editor.getCursorPosition()
			highlight = @highlightedWordManager.findHighlightWithinRange
				start: cursor
				end: cursor
			return highlight

		runSpellCheckSoon: (delay = 1000) ->
			run = () =>
				delete @timeoutId
				@runSpellCheck(@updatedLines)
				@updatedLines = []
			if @timeoutId?
				clearTimeout @timeoutId
			@timeoutId = setTimeout run, delay

		markLinesAsUpdated: (change) ->
			start = change.start

							seen[key] = true
					displayResult highlights

		apiRequest: (endpoint, data, callback = (error, result) ->)->
			data.token = window.user.id
			data._csrf = window.csrfToken
			# use angular timeout option to cancel request if doc is changed
			requestHandler = @$q.defer()
			options = {timeout: requestHandler.promise}
			httpRequest = @$http.post("/spelling" + endpoint, data, options)
			.then (response) =>
				callback(null, response.data)
			.catch (response) =>
				callback(new Error('api failure'))
			# provide a method to cancel the request
			abortRequest = () ->
				requestHandler.resolve()
			return { abort: abortRequest }

		getWords: (linesToProcess) ->
			lines = @adapter.getLines()
			words = []
			positions = []
			for line, row in lines
