'use babel'

/* @flow */

import { CompositeDisposable, Emitter, Disposable } from 'atom'
import { getMessageClass } from './helpers'
import { getElement as getGutterElement } from './elements/gutter'
import type { TextEditor, TextBuffer, TextEditorMarker } from 'atom'
import type { Linter$Message } from './types'
import type Editor from './editor'

export default class Buffer {
  emitter: Emitter;
  markers: Object; // Object<string, TextEditorMarker>
  messages: Set<Linter$Message>;
  textBuffer: TextBuffer;
  textEditors: Set<TextEditor>;
  subscriptions: CompositeDisposable;

  constructor(textBuffer: TextBuffer) {
    this.emitter = new Emitter()
    this.markers = { }
    this.messages = new Set()
    this.textBuffer = textBuffer
    this.textEditors = new Set()
    this.subscriptions = new CompositeDisposable()

    this.subscriptions.add(this.emitter)
    this.subscriptions.add(textBuffer.onDidDestroy(() => {
      this.dispose()
    }))
  }
  getBuffer(): TextBuffer {
    return this.textBuffer
  }
  attachEditor(editor: Editor) {
    this.textEditors.add(editor)
    this.subscriptions.add(editor)
    editor.onDidDestroy(() => {
      this.subscriptions.remove(editor)
      this.textEditors.delete(editor)
    })
  }
  apply(added: Array<Linter$Message>, removed: Array<Linter$Message>) {
    for (const message of removed) {
      const marker = this.markers[message.id]
      if (marker) {
        marker.destroy()
        this.markers[message.id] = null
      }
      this.messages.delete(message)
    }

    for (const message of added) {
      const marker = this.textBuffer.markRange(message.range, {
        invalidate: 'never',
        persistent: false
      })
      this.markers[message.id] = marker
      this.messages.add(message)
      const messageClass = getMessageClass(message)
      for (const editor of this.textEditors) {
        editor.textEditor.decorateMarker(marker, {
          type: 'highlight',
          class: `linter-highlight ${messageClass}`
        })
        if (editor.gutter) {
          editor.gutter.decorateMarker(marker, {
            class: 'linter-row',
            item: getGutterElement(messageClass)
          })
        }
      }
    }
  }
  onDidDestroy(callback: Function): Disposable {
    return this.emitter.on('did-destroy', callback)
  }
  dispose() {
    this.emitter.emit('did-destroy')
    this.subscriptions.dispose()

    for (const key in this.markers) {
      const value = this.markers[key]
      if (value) {
        value.destroy()
      }
    }
    this.markers = { }
  }
}

@@ -1357,32 +1357,33 @@
     const marker
+s
  = this.markers%5B
@@ -1410,16 +1410,17 @@
  (marker
+s
 ) %7B%0A    
@@ -1427,120 +1427,199 @@
     
+if (
 marker
-.destroy()%0A        this.markers%5Bmessage.id%5D = null
+s.length === 1) %7B%0A          markers%5B0%5D.destroy()%0A        %7D else if (markers.length === 2) %7B
 %0A    
-  %7D%0A
       
-this.messages.delete(message)%0A    %7D%0A%0A
+markers%5B0%5D.destroy()%0A          markers%5B1%5D.destroy()%0A        %7D else %7B%0A     
     
+ 
 for 
@@ -1630,23 +1630,24 @@
 st m
-essage of added
+arker of markers
 ) %7B%0A
@@ -1656,129 +1656,203 @@
     
-const
+     
  marker
- = this.textBuffer.markRange(message.range, %7B%0A        invalidate: 'never',
+.destroy()%0A          %7D%0A        %7D%0A        this.markers%5Bmessage.id%5D = null%0A      %7D%0A      this.messages.delete(message)
 %0A    
+%7D%0A%0A
     
-persistent: false%0A      %7D)
+for (const message of added) %7B%0A      const markers = %5B%5D
 %0A   
@@ -1887,16 +1887,17 @@
 = marker
+s
 %0A      t
@@ -2017,24 +2017,168 @@
 tEditors) %7B%0A
+        const marker = editor.textEditor.markBufferRange(message.range, %7B%0A          invalidate: 'never',%0A          persistent: false%0A        %7D)%0A
         edit
@@ -2487,24 +2487,53 @@
 )%0A        %7D%0A
+        markers.push(marker)%0A
       %7D%0A    

Mark display buffer instead of text buffer