import expect from "expect"

describe("EditorLayout", function() {
  let EditorLayout

  // If alert isn't defined, create a dummy one, and remember to clean it up afterwards
  if (typeof global.alert === "undefined") {
    before(function () {
      global.alert = function() { }
    })
    after(function () {
      delete global.alert
    })
  }

  // Same for FileReader
  if (typeof global.FileReader === "undefined") {
    before(function () {
      global.FileReader = function() {}
    })
    after(function () {
      delete global.FileReader
    })
  }

  // Create spies for alert and FileReader, and then load the module under test.
  before(function () {
    expect.spyOn(global, "alert")
    expect.spyOn(global, "FileReader")
    EditorLayout = require("src/layout").default
  })
  // Undo the spies afterwards
  after(function () {
    expect.restoreSpies()
  })

  // Reset spies after each test
  afterEach(function () {
    global.alert.reset()
    global.FileReader.reset()
  })

  describe("when file(s) are dropped", function() {
    describe("if one or more files are of an unexpected type", function() {
      it("should alert the user that their file(s) were rejected", () => {
        const editorLayout = new EditorLayout()

        editorLayout.onDrop([], ["rejected.file.1"])
        editorLayout.onDrop([], ["rejected.file.1", "rejected.file.2"])

        expect(global.alert.calls.length).toEqual(2)

        global.alert.calls.forEach(call => {
          expect(call.arguments[0]).toMatch(/^Sorry.*/)
        })
      })
    })

    describe("if more than one file of an expected type is dropped", function() {
      it("should alert the user that their file(s) were rejected", () => {
        const editorLayout = new EditorLayout()

        editorLayout.onDrop(["accepted.file.1", "accepted.file.2"], [])
        expect(global.alert.calls.length).toEqual(1)
        expect(global.alert.calls[0].arguments[0]).toMatch(/^Sorry.*/)
      })
    })

    describe("if exactly one file of an expected type is dropped", function() {
      it("should call the updateSpec function passed in as props with the contents of the file", () => {
        const fileContents = "This is my awesome file!"
        const props = {
          specActions: {
            updateSpec: expect.createSpy()
          }
        }
        global.FileReader.andReturn({
          readAsText: function () { this.onloadend() },
          result: fileContents
        })

        const editorLayout = new EditorLayout(props)

        editorLayout.onDrop(["accepted.file"])

        expect(props.specActions.updateSpec).toHaveBeenCalledWith(fileContents, "fileDrop")
      })
    })
  })

  describe("onChange", function() {
    it("should call specActions.updateSpec with origin = editor by default", function() {
      // Given
      const spy = expect.createSpy()
      const props ={
        specActions: {
          updateSpec: spy
        }
      }
      const editorLayout = new EditorLayout(props)

      // When
      editorLayout.onChange("one: 1")

      // Then
      expect(spy.calls.length).toEqual(1)
      expect(spy.calls[0].arguments).toEqual(["one: 1", "editor"])
    })

    it("should allow (onDrop) to override with different origin", function() {
      // Given
      const spy = expect.createSpy()
      const props ={
        specActions: {
          updateSpec: spy
        }
      }
      const editorLayout = new EditorLayout(props)

      // When
      editorLayout.onChange("one: 1", "somethingElse")

      // Then
      expect(spy.calls.length).toEqual(1)
      expect(spy.calls[0].arguments).toEqual(["one: 1", "somethingElse"])
    })
  })
})