'use babel';
import {
  CompositeDisposable,
  Point,
} from 'atom';

import minimapCodeglanceElement from './minimap-codeglance-element.js';

import {
  addEventListener,
  addEventListenerOnce,
} from './utils.js';

var prototype = {
  initialize() {
    this.element = minimapCodeglanceElement();

    this.disposables = new CompositeDisposable(
      atom.config.observe('minimap-codeglance.numberOfLines', numberOfLines =>
        this.numberOfLines = numberOfLines
      ),
      atom.config.observe('minimap-codeglance.showLineNumbers', showLineNumbers =>
        showLineNumbers ? this.element.showLineNumbers() : this.element.hideLineNumbers()
      ),
      atom.config.observe('minimap-codeglance.codeHighlighting', codeHighlighting =>
        this.codeHighlighting = codeHighlighting
      ),
      atom.config.observe('minimap-codeglance.softWrap', softWrapMode =>
        this.softWrapMode = softWrapMode
      ),
      addEventListener(document.body, 'mousedown', () =>
        this.disableDuringMouseDown()
      ),
    );
  },

  destroy() {
    this.element.destroy();
    this.disposables.dispose();
    [this.element, this.disposables, this.minimap] = [];
  },

  disabled: false,

  disableDuringMouseDown() {
    if(this.disabled) return;
    this.disabled = true;
    this.element.hide();
    addEventListenerOnce(document.body, 'mouseup', () =>
      this.disabled = false
    );
  },

  addMinimap(minimap) {
    var minimapView = atom.views.getView(minimap);

    var minimapDisposable = new CompositeDisposable(
      addEventListener(minimapView, 'mouseenter', () =>
        this.setCurrentMinimap(minimap)
      ),
      addEventListener(minimapView, 'mousemove', event =>
        this.scrollToMousePosition(event)
      ),
      addEventListener(minimapView, 'mouseleave', () =>
        this.detachElement()
      ),
      minimap.onDidDestroy(() => {
        this.disposables.remove(minimapDisposable);
        minimapDisposable.dispose();
        minimapDisposable = null;
      }),
    );

    this.disposables.add(minimapDisposable);
  },

  setCurrentMinimap(minimap) {
    this.minimap = minimap;
    this.attachElement();
    this.updateNumberOfLines();
    this.updateSoftWrapped();

    if(this.getTextEditor().getText() == this.element.getText()) return;

    this.element.setText('');
    this.updateGrammar();
    this.updateText();
  },

  getTextEditor() {
    return this.minimap.getTextEditor();
  },

  getTextEditorRoot() {
    var textEditorView = atom.views.getView(this.getTextEditor());
    return textEditorView.shadowRoot || textEditorView;
  },

  attachElement() {
    var textEditorRoot = this.getTextEditorRoot();
    textEditorRoot.querySelector('.editor-contents--private').appendChild(this.element);
  },

  detachElement() {
    this.element.remove();
  },

  updateNumberOfLines() {
    this.element.setNumberOfLines(this.numberOfLines);
  },

  updateSoftWrapped() {
    this.element.setSoftWrapped(this.getSoftWrapped());
  },

  getSoftWrapped() {
    switch(this.softWrapMode.split(' ')[0]) {
      default:
      case 'editor':
        return this.getTextEditor().isSoftWrapped();
      case 'always':
        return true;
      case 'never':
        return false;
    }
  },

  updateGrammar() {
    this.element.setGrammar(
      this.codeHighlighting ?
        this.getTextEditor().getGrammar() :
        atom.grammars.grammarForScopeName('text.plain.null-grammar')
    );
  },

  updateText() {
    this.element.setText(this.getTextEditor().getText());
  },

  scrollToMousePosition({offsetX, offsetY}) {
    if(this.disabled || !this.minimap) return;
    var screenPosition = this.screenPositionForOffset({offsetX, offsetY});

    if(screenPosition.row > this.getTextEditor().getLastScreenRow()) {
      return void this.element.hide();
    }

    this.element.show();
    this.element.scrollToBufferPosition(
      this.getTextEditor().bufferPositionForScreenPosition(screenPosition)
    );
    this.element.translateY(offsetY);
  },

  screenPositionForOffset({offsetX, offsetY}) {
    var firstVisibleScreenRow = this.minimap.getFirstVisibleScreenRow();
    var lineHeight = this.minimap.charHeight + this.minimap.interline;
    var row = firstVisibleScreenRow + Math.floor(offsetY / lineHeight);
    var columnWidth = this.minimap.charWidth;
    var column = Math.floor(offsetX / columnWidth);
    return new Point(row, column);
  },
};

export default function minimapCodeglance() {
  return Object.create(prototype);
}

@@ -929,134 +929,56 @@
     
-  addEventListener(document.body, 'mousedown', () =%3E%0A        this.disableDuringMouseDown()%0A      ),%0A    );%0A  %7D,%0A%0A  destroy() %7B
+);%0A  %7D,%0A%0A  destroy() %7B%0A    this.detachElement();
 %0A   
@@ -1207,36 +1207,37 @@
 e;%0A    this.
-e
+detachE
 lement
-.hide
 ();%0A    addE
@@ -1280,24 +1280,26 @@
 seup', () =%3E
+ %7B
 %0A      this.
@@ -1314,21 +1314,78 @@
  = false
+;
 %0A    
+  this.attachElement();%0A      this.element.hide();%0A    %7D
 );%0A  %7D,%0A
@@ -1818,24 +1818,260 @@
 ()%0A      ),%0A
+      addEventListener(minimapView, 'mousedown', () =%3E%0A        this.disableDuringMouseDown()%0A      ),%0A      addEventListener(atom.views.getView(minimap.getTextEditor()), 'mousedown', () =%3E%0A        this.disableDuringMouseDown()%0A      ),%0A
       minima

fix some issues where no text was visible