import ReactDOM from 'react-dom'
import ReactTestUtils from 'react-dom/test-utils'
import { fromJS, List, Map } from 'immutable'

import IconArrowOpenUpLine from '@instructure/ui-icons/lib/Line/IconArrowOpenUp'
import IconArrowOpenDownLine from '@instructure/ui-icons/lib/Line/IconArrowOpenDown'
import Transition from '@instructure/ui-motion/lib/components/Transition'

import PositionSummary from '../../../PositionSummary'
import QuizEntry from '../../../../../../records/QuizEntry'
import SessionItem from '../../../../../../records/SessionItem'
import Collection from '../presenter'
import styles from '../styles.css'

describe('Common Stimulus Sidebar Collection Presenter', () => {
  const itemCollection = fromJS([{}, {}, {}])
  const renderSidebarItemStub = sinon.stub()
  const setSidebarStimulusIsShowingStub = sinon.stub()

  const props = {
    firstPosition: 1,
    isShowingItems: false,
    sidebarOpen: true,
    renderSidebarItem: renderSidebarItemStub,
    stimulusId: '1',
    itemCollection,
    setSidebarStimulusIsShowing: setSidebarStimulusIsShowingStub
  }

  afterEach(() => {
    renderSidebarItemStub.resetHistory()
    setSidebarStimulusIsShowingStub.resetHistory()
  })

  const testbed = createTestbed(Collection, props)

  const sharedItemsRenderExample = (itemCollection, props = {}) => {
    it('renders items', () => {
      testbed.render({itemCollection, ...props})
      expect(renderSidebarItemStub.callCount).to.eq(itemCollection.size)
    })
  }

  it('calls the render function with the right display positions on Build', () => {
    testbed.render({
      itemCollection: List([
        new QuizEntry({ entryType: 'Bank', properties: Map({ sampleNum: 3 }) }),
        new QuizEntry()
      ])
    })
    expect(renderSidebarItemStub.firstCall.args[1]).to.equal(1)
    expect(renderSidebarItemStub.firstCall.args[2]).to.equal(true)
    expect(renderSidebarItemStub.secondCall.args[1]).to.equal(4)
  })

  it('calls the render function with the right sidebarOpen argument', () => {
    testbed.render({
      sidebarOpen: false,
      itemCollection: List([
        new QuizEntry({ entryType: 'Bank', properties: Map({ sampleNum: 3 }) }),
        new QuizEntry()
      ])
    })
    expect(renderSidebarItemStub.firstCall.args[2]).to.equal(false)
  })

  it('calls the render function with the right display positions on Take', () => {
    testbed.render({
      itemCollection: List([
        new SessionItem(),
        new SessionItem()
      ])
    })
    expect(renderSidebarItemStub.firstCall.args[1]).to.equal(1)
    expect(renderSidebarItemStub.secondCall.args[1]).to.equal(2)
  })

  context('with more than 5 items', () => {
    const items = fromJS([{}, {}, {}, {}, {}, {}])

    context('with isShowingItems true', () => {
      sharedItemsRenderExample(items, {isShowingItems: true})

      it('renders an iconUpArrow', () => {
        testbed.render({itemCollection: items, isShowingItems: true})
        expect(testbed.findChildrenByType(IconArrowOpenUpLine)).to.not.be.empty()
      })
    })

    context('with sidebarOpen true and not showing items', () => {
      it('renders a div with hideAll applied', () => {
        testbed.render({itemCollection: items, sidebarOpen: true})
        expect(testbed.findChildrenByClass(styles.hideAll)).to.not.be.empty()
      })
    })

    context('with sidebarOpen false', () => {
      it('renders a div with hideAll applied', () => {
        testbed.render({itemCollection: items, sidebarOpen: false})
        expect(testbed.findChildrenByClass(styles.hideAll)).to.not.be.empty()
      })

      context('with isShowingItems true', () => {
        sharedItemsRenderExample(items, {isShowingItems: true, sidebarOpen: false})

        it('renders an iconUpArrow', () => {
          testbed.render({itemCollection: items, isShowingItems: true, sidebarOpen: false})
          expect(testbed.findChildrenByType(IconArrowOpenUpLine)).to.not.be.empty()
        })
      })

      const sharedRender = () => { testbed.render({itemCollection: items, sidebarOpen: false}) }

      it('renders an IconDownArrow', () => {
        sharedRender()
        expect(testbed.findChildrenByType(IconArrowOpenDownLine)).to.not.be.empty()
      })

      it('renders a summary of the items', () => {
        sharedRender()
        expect(testbed.findChildrenByType(PositionSummary)).to.not.be.empty()
      })

      it('renders the first and last position of the items', () => {
        sharedRender()
        const text = testbed.getText()
        expect(text).to.include(props.firstPosition)
        expect(text).to.include((props.firstPosition + items.size) - 1)
      })

      it('does not render intermediate position numbers', () => {
        sharedRender()
        const text = testbed.getText()
        expect(text).to.not.include(props.firstPosition + 1)
      })
    })

    sharedItemsRenderExample(items)
  })

  context('with fewer than 6 items', () => {
    const items = fromJS([{}, {}, {}])
    const sharedRenderExample = (props, transitionIn) => {
      it('hides the arrows', () => {
        testbed.render({itemCollection: items, ...props})
        expect(testbed.findChildrenByClass(styles.hideAll).length).to.eq(2)
        expect(testbed.findChildrenByType(Transition)[0].props.in).to.eq(transitionIn)
      })
    }

    context('with isShowingItems true', () => {
      sharedItemsRenderExample(items, {isShowingItems: true})
      sharedRenderExample({isShowingItems: true}, false)
    })

    context('with sidebarOpen false', () => {
      sharedItemsRenderExample(items, {sidebarOpen: false})
      sharedRenderExample({sidebarOpen: false}, true)
    })

    context('with sidebarOpen true and not showing items', () => {
      sharedItemsRenderExample(items, {sidebarOpen: true})
      sharedRenderExample({sidebarOpen: true}, true)
    })

    sharedItemsRenderExample(items)
    sharedRenderExample({}, true)
  })

  it('sets the sidebar showing items to false when clicking ArrowOpenDown arrow', () => {
    testbed.render()
    const arrow = ReactDOM.findDOMNode(testbed.findChildByType(IconArrowOpenDownLine))
    ReactTestUtils.Simulate.click(arrow)
    expect(setSidebarStimulusIsShowingStub.calledWith('1', true)).to.be.true()
  })

  it('sets the sidebar showing items to false when clicking ArrowOpenUp arrow', () => {
    testbed.render()
    const arrow = ReactDOM.findDOMNode(testbed.findChildByType(IconArrowOpenUpLine))
    ReactTestUtils.Simulate.click(arrow)
    expect(setSidebarStimulusIsShowingStub.calledWith('1', false)).to.be.true()
  })

  describe('a11y tests', () => {
    it('should meet a11y standards', (done) => {
      testbed.render()
      testbed.checkA11yStandards(done)
    })
  })
})
