 			else if change.action == "remove"
 				@updatedLines[start.row] = true
 				removeLines()
+
+		runSpellCheckSoon: (delay = 1000) ->
+			run = () =>
+				delete @timeoutId
+				@runSpellCheck(@updatedLines)
+				@updatedLines = []
+			if @timeoutId?
+				clearTimeout @timeoutId
+			@timeoutId = setTimeout run, delay
 
 		runSpellCheck: (linesToProcess) ->
 			{words, positions} = @getWords(linesToProcess)

			displayResult = (highlights) =>
				if linesToProcess?
					for shouldProcess, row in linesToProcess
						@highlightedWordManager.clearRows(row, row) if shouldProcess
				else
					@highlightedWordManager.clearRows()
				for highlight in highlights
					@highlightedWordManager.addHighlight highlight

			if not words.length
				displayResult highlights

define [], () ->
	class SpellCheckManager
		constructor: (@$scope, @cache, @$http, @$q, @adapter) ->
			@inProgressRequest = null
			@updatedLines = []

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

		init: () ->
			@updatedLines = Array(@adapter.getLines().length).fill(true)
			@runSpellCheckSoon(200) if @isSpellCheckEnabled()

		isSpellCheckEnabled: () ->
			return !!(
				@$scope.spellCheck and
				@$scope.spellCheckLanguage and
				@$scope.spellCheckLanguage != ''
			)

		onChange: (e) =>
			if @isSpellCheckEnabled()
				@markLinesAsUpdated(@adapter.normalizeChangeEvent(e))
				@runSpellCheckSoon()

		onSessionChange: () =>
			@adapter.wordManager.reset()
			@inProgressRequest.abort() if @inProgressRequest?

			@runSpellCheckSoon(200) if @isSpellCheckEnabled()

		runFullCheck: () ->
			@adapter.wordManager.reset()
			@runSpellCheck() if @isSpellCheckEnabled()

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