'use babel';
import 'object-assign-shim';

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

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

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

var prototype = {
  initialize() {
    this.element = minimapCodeglanceElement();
    this.disposables = new CompositeDisposable(
      observeConfig('showLineNumbers', showLineNumbers =>
        this.element.updateLineNumbers(showLineNumbers)
      ),
      observeConfig('displayMinimapOnLeft', 'minimap', showOnLeft =>
        this.updatePosition(showOnLeft)
      ),
    );
  },

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

  updatePosition(showOnLeft) {
    if(!this.minimap) return;

    var minimapWidth = `${getView(this.minimap).clientWidth}px`;
    Object.assign(this.element.style, {
      left: showOnLeft ? minimapWidth : 0,
      right: showOnLeft ? 0 : minimapWidth,
    });

    this.fixTypeWriterEditor();
  },

  // support for typewriter (https://atom.io/packages/typewriter)
  fixTypeWriterEditor() {
    var textEditorView = this.getTextEditorView();
    var isTypeWriter = textEditorView.getAttribute('data-typewriter');

    if(isTypeWriter) {
      this.element.style.margin = getComputedStyle(textEditorView).margin;

      var hideLineNumbers = getConfig('hideLineNumbersInTypeWriter');
      if(hideLineNumbers) this.element.updateLineNumbers(false, 0);
    } else {
      this.element.style.margin = '';
      this.element.updateLineNumbers(getConfig('showLineNumbers'));
    }
  },

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

  addMinimap(minimap) {
    var minimapView = getView(minimap);
    var textEditorView = getView(minimap.getTextEditor());

    var minimapDisposable = new CompositeDisposable(
      addEventListener(minimapView, 'mouseenter', () =>
        this.setCurrentMinimap(minimap)
      ),
      addEventListener(minimapView, 'mousemove', event => {
        if(this.minimap != minimap) {
          this.setCurrentMinimap(minimap);
        }

        this.scrollToMinimapOffset(event);
      }),
      addEventListener(minimapView, 'mouseleave', () =>
        this.element.hide()
      ),
      addEventListener(textEditorView, 'mousedown', () =>
        this.disableDuringMouseDown()
      ),
      minimap.onDidDestroy(() => {
        this.disposables.remove(minimapDisposable);
        minimapDisposable.dispose();
        minimapDisposable = null;

        if(this.getTextEditor() == minimap.getTextEditor()) {
          this.element.hide();
        }
      }),
    );

    this.disposables.add(minimapDisposable);
  },

  setCurrentMinimap(minimap) {
    if(this.minimap != minimap) {
      this.minimap = minimap;
      this.attachElement();
      this.updatePosition();
    }

    this.element.update(this.getTextEditor());
  },

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

  getTextEditorView() {
    return getView(this.getTextEditor());
  },

  attachElement() {
    this.getTextEditorView().parentNode.appendChild(this.element);
  },

  scrollToMinimapOffset({offsetX, offsetY}) {
    if(this.disabled || !this.getTextEditor()) return;
    var screenPosition = this.screenPositionForMinimapOffset(offsetX, offsetY);

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

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

  screenPositionForMinimapOffset(offsetX, offsetY) {
    var firstVisibleScreenRow = this.minimap.getFirstVisibleScreenRow();
    var row = firstVisibleScreenRow + Math.floor(offsetY / this.getLineHeight());
    var column = Math.floor(offsetX / this.getColumnWidth());
    return new Point(row, column);
  },

  getLineHeight() {
    var {charHeight, interline} = this.minimap;
    if(!charHeight) charHeight = this.minimap.configCharHeight;
    if(!interline) interline = this.minimap.configInterline;
    return charHeight + interline;
  },

  getColumnWidth() {
    var {charWidth} = this.minimap;
    if(!charWidth) charWidth = this.minimap.configCharWidth;
    return charWidth;
  },

  translateY(offsetY) {
    var codeglanceHeight = this.element.clientHeight;
    var textEditorHeight = this.getTextEditorView().clientHeight;

    offsetY -= codeglanceHeight / 2;
    offsetY = Math.round(offsetY);
    offsetY = Math.max(0, offsetY);
    offsetY = Math.min(textEditorHeight - codeglanceHeight, offsetY);
    requestAnimationFrame(() => this.element.style.transform = `translateY(${offsetY}px)`);
  },
};

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

@@ -3999,98 +3999,118 @@
 var 
-row = firstVisibleScreenRow + Math.floor(offsetY / this.getLineHeight());%0A    var column =
+lineHeight = this.minimap.getCharHeight() + this.minimap.getInterline();%0A    var row = firstVisibleScreenRow +
  Mat
@@ -4127,83 +4127,13 @@
 fset
-X / this.getColumnWidth());%0A    return new Point(row, column);%0A  %7D,%0A%0A  getL
+Y / l
 ineH
@@ -4137,20 +4137,18 @@
 neHeight
-() %7B
+);
 %0A    var
@@ -4152,220 +4152,90 @@
 var 
-%7BcharHeight, interline%7D = this.minimap;%0A    if(!charHeight) charHeight = this.minimap.configCharHeight;%0A    if(!interline) interline = this.minimap.configInterline;%0A    return charHeight + interline;%0A  %7D,%0A%0A  getC
+columnWidth = this.minimap.getCharWidth();%0A    var column = Math.floor(offsetX / c
 olum
@@ -4244,130 +4244,44 @@
 idth
-() %7B
+);
 %0A    
-var %7BcharWidth%7D = this.minimap;%0A    if(!charWidth) charWidth = this.minimap.configCharWidth;%0A    return charWidth
+return new Point(row, column)
 ;%0A  

use minimap api for measurements