'use babel'

/* eslint-env jasmine */

import GoToLineView from '../lib/go-to-line-view'

describe('GoToLine', () => {
  let editor = null
  let editorView = null
  let goToLine = null

  beforeEach(() => {
    waitsForPromise(() => {
      return atom.workspace.open('sample.js')
    })

    runs(() => {
      const workspaceElement = atom.views.getView(atom.workspace)
      workspaceElement.style.height = '200px'
      workspaceElement.style.width = '1000px'
      jasmine.attachToDOM(workspaceElement)
      editor = atom.workspace.getActiveTextEditor()
      editorView = atom.views.getView(editor)
      goToLine = GoToLineView.activate()
      editor.setCursorBufferPosition([1, 0])
    })
  })

  describe('when go-to-line:toggle is triggered', () => {
    it('adds a modal panel', () => {
      expect(goToLine.panel.isVisible()).toBeFalsy()
      atom.commands.dispatch(editorView, 'go-to-line:toggle')
      expect(goToLine.panel.isVisible()).toBeTruthy()
    })
  })

  describe('when entering a line number', () => {
    it('only allows 0-9 and the colon character to be entered in the mini editor', () => {
      expect(goToLine.miniEditor.getText()).toBe('')
      goToLine.miniEditor.insertText('a')
      expect(goToLine.miniEditor.getText()).toBe('')
      goToLine.miniEditor.insertText('path/file.txt:56')
      expect(goToLine.miniEditor.getText()).toBe('')
      goToLine.miniEditor.insertText(':')
      expect(goToLine.miniEditor.getText()).toBe(':')
      goToLine.miniEditor.setText('')
      goToLine.miniEditor.insertText('4')
      expect(goToLine.miniEditor.getText()).toBe('4')
    })
  })

  describe('when typing line numbers (auto-navigation)', () => {
    it('automatically scrolls to the desired line', () => {
      goToLine.miniEditor.insertText('19')
      expect(editor.getCursorBufferPosition()).toEqual([18, 0])
    })
  })

  describe('when typing line and column numbers (auto-navigation)', () => {
    it('automatically scrolls to the desired line and column', () => {
      goToLine.miniEditor.insertText('3:8')
      expect(editor.getCursorBufferPosition()).toEqual([2, 7])
    })
  })

  describe('when entering a line number and column number', () => {
    it('moves the cursor to the column number of the line specified', () => {
      expect(goToLine.miniEditor.getText()).toBe('')
      goToLine.miniEditor.insertText('3:14')
      atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
      expect(editor.getCursorBufferPosition()).toEqual([2, 13])
    })

    it('centers the selected line', () => {
      goToLine.miniEditor.insertText('45:4')
      atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
      const rowsPerPage = editor.getRowsPerPage()
      const currentRow = editor.getCursorBufferPosition().row - 1
      expect(editor.getFirstVisibleScreenRow()).toBe(
        currentRow - Math.ceil(rowsPerPage / 2)
      )
      expect(editor.getLastVisibleScreenRow()).toBe(
        currentRow + Math.floor(rowsPerPage / 2)
      )
    })
  })

  describe('when entering a line number greater than the number of rows in the buffer', () => {
    it('moves the cursor position to the first character of the last line', () => {
      atom.commands.dispatch(editorView, 'go-to-line:toggle')
      expect(goToLine.panel.isVisible()).toBeTruthy()
      expect(goToLine.miniEditor.getText()).toBe('')
      goToLine.miniEditor.insertText('78')
      atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
      expect(goToLine.panel.isVisible()).toBeFalsy()
      expect(editor.getCursorBufferPosition()).toEqual([77, 0])
    })
  })

  describe('when entering a column number greater than the number in the specified line', () => {
    it('moves the cursor position to the last character of the specified line', () => {
      atom.commands.dispatch(editorView, 'go-to-line:toggle')
      expect(goToLine.panel.isVisible()).toBeTruthy()
      expect(goToLine.miniEditor.getText()).toBe('')
      goToLine.miniEditor.insertText('3:43')
      atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
      expect(goToLine.panel.isVisible()).toBeFalsy()
      expect(editor.getCursorBufferPosition()).toEqual([2, 39])
    })
  })

  describe('when core:confirm is triggered', () => {
    describe('when a line number has been entered', () => {
      it('moves the cursor to the first character of the line', () => {
        goToLine.miniEditor.insertText('3')
        atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
        expect(editor.getCursorBufferPosition()).toEqual([2, 4])
      })
    })

    describe('when the line number entered is nested within foldes', () => {
      it('unfolds all folds containing the given row', () => {
        expect(editor.indentationForBufferRow(9)).toEqual(3)
        editor.foldAll()
        expect(editor.screenRowForBufferRow(9)).toEqual(0)
        goToLine.miniEditor.insertText('10')
        atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
        expect(editor.getCursorBufferPosition()).toEqual([9, 6])
      })
    })
  })

  describe('when no line number has been entered', () => {
    it('closes the view and does not update the cursor position', () => {
      atom.commands.dispatch(editorView, 'go-to-line:toggle')
      expect(goToLine.panel.isVisible()).toBeTruthy()
      atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
      expect(goToLine.panel.isVisible()).toBeFalsy()
      expect(editor.getCursorBufferPosition()).toEqual([1, 0])
    })
  })

  describe('when no line number has been entered, but a column number has been entered', () => {
    it('navigates to the column of the current line', () => {
      atom.commands.dispatch(editorView, 'go-to-line:toggle')
      expect(goToLine.panel.isVisible()).toBeTruthy()
      goToLine.miniEditor.insertText('4:1')
      atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
      expect(goToLine.panel.isVisible()).toBeFalsy()
      expect(editor.getCursorBufferPosition()).toEqual([3, 0])
      atom.commands.dispatch(editorView, 'go-to-line:toggle')
      expect(goToLine.panel.isVisible()).toBeTruthy()
      goToLine.miniEditor.insertText(':19')
      atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
      expect(goToLine.panel.isVisible()).toBeFalsy()
      expect(editor.getCursorBufferPosition()).toEqual([3, 18])
    })
  })

  describe('when core:cancel is triggered', () => {
    it('closes the view and does not update the cursor position', () => {
      atom.commands.dispatch(editorView, 'go-to-line:toggle')
      expect(goToLine.panel.isVisible()).toBeTruthy()
      atom.commands.dispatch(goToLine.miniEditor.element, 'core:cancel')
      expect(goToLine.panel.isVisible()).toBeFalsy()
      expect(editor.getCursorBufferPosition()).toEqual([1, 0])
    })
  })
})
