import { List } from 'immutable'
import InteractionType from 'quiz-interactions/lib/records/interactions/multiple_choice'

import { wrapInDragAndDropTestContext } from '../../../../../../tests/util/dndTestUtils'

import QuizEntry from '../../../../../common/records/QuizEntry'
import Item from '../../../../../common/records/Item'
import Bank from '../../../../../common/records/Bank'
import BankEntry from '../../../../../common/records/BankEntry'
import StimulusRecord from '../../../../../common/records/Stimulus'

import Sidebar from '../presenter'
import SidebarItem from '../SidebarItem'
import Stimulus from '../Stimulus'

import CommonSidebar from '../../../../../common/components/layout/sidebar/Sidebar'

import styles from '../styles.css'

describe('Building Sidebar Presenter', () => {
  const intType = new InteractionType({})
  const itemA = new Item({id: '5', itemBody: '<div>first</div>&amp;<div>second</div>'})
  const itemB = new Item({id: '6'})
  const bank = new Bank({id: '8', title: '<div>nohtml</div>'})
  const stimulus = new StimulusRecord({id: '10'})
  const bankEntry = new BankEntry({id: '11'})
  sinon.stub(itemA, 'getInteractionType').returns(intType)
  sinon.stub(itemB, 'getInteractionType').returns(intType)
  sinon.stub(bankEntry, 'getEntry').returns(itemA)
  const quizEntryA = new QuizEntry({ id: '3', entryType: 'Item', position: 4 })
  const quizEntryB = new QuizEntry({ id: '8', entryType: 'Item', position: 8 })
  const quizEntryC = new QuizEntry({ id: '9', entryType: 'Bank', position: 9 })
  const quizEntryD = new QuizEntry({ id: '11', entryType: 'BankEntry', position: 10 })
  const quizEntryE = new QuizEntry({ id: '10', entryType: 'Stimulus', position: 11 })
  sinon.stub(quizEntryA, 'getEntry').returns(itemA)
  sinon.stub(quizEntryB, 'getEntry').returns(itemB)
  sinon.stub(quizEntryC, 'getEntry').returns(bank)
  sinon.stub(quizEntryD, 'getEntry').returns(bankEntry)
  sinon.stub(quizEntryE, 'getEntry').returns(stimulus)
  const quizEntries = List([
    quizEntryA, quizEntryB, quizEntryC, quizEntryD
  ])
  const noop = () => {}

  const props = {
    connectDropTarget: (Component) => (Component), // inserted by React DnD
    isOver: false, // inserted by React DnD
    moveQuizEntry: noop, // Used for DND
    moveTemporaryQuizEntry: noop, // Used for DND
    newHoverPosition: noop, // Used for DND
    quizId: '1', // Used for DND
    scrollToItem: noop,
    sidebarOpen: true,
    toggleSidebar: () => {},
    quizEntries,
    totalPointsPossible: 4
  }

  const testbed = createTestbed(
    withContext(
      wrapInDragAndDropTestContext(Sidebar)
    ),
    props)

  describe('#renderSidebarItems', () => {
    it('renders the correct number', () => {
      testbed.render()
      const sidebarItems = testbed.findChildrenByType(SidebarItem)
      expect(sidebarItems.length).to.eq(8)

      const openItems = document.querySelector(`.${styles.openItems}`)
      expect(openItems.childNodes.length).to.eq(4)

      const closedItems = document.querySelector(`.${styles.closedItems}`)
      expect(closedItems.childNodes.length).to.eq(4)
    })

    it('renders with the sidebarIsOpen class when sidebar is open', () => {
      testbed.render({sidebarOpen: true})
      expect(!!document.querySelector(`.${styles.sidebarIsOpen}`)).to.be.true()
      expect(!!document.querySelector(`.${styles.sidebarIsClosed}`)).to.be.false()
    })

    it('renders with the sidebarIsClosed class when sidebar is closed', () => {
      testbed.render({sidebarOpen: false})
      expect(!!document.querySelector(`.${styles.sidebarIsOpen}`)).to.be.false()
      expect(!!document.querySelector(`.${styles.sidebarIsClosed}`)).to.be.true()
    })

    it('should extract text content of item body HTML', () => {
      testbed.render()
      const sidebarItems = testbed.findChildrenByType(SidebarItem)
      expect(sidebarItems[0].props.itemBody).to.eq('first&second')
      expect(sidebarItems[3].props.itemBody).to.eq('first&second')
    })

    it('should not extract text content of bank title', () => {
      testbed.render()
      const sidebarItems = testbed.findChildrenByType(SidebarItem)
      expect(sidebarItems[2].props.itemBody).to.eq('<div>nohtml</div>')
    })
  })

  describe('#render', () => {
    it('renders the common sidebar', () => {
      testbed.render()
      expect(testbed.findChildrenByType(CommonSidebar).length).to.eq(1)
    })

    it('passes the role prop to the CommonSidebar component', () => {
      const role = 'complementary'
      testbed.render({ role })
      const commonSidebar = testbed.findChildByType(CommonSidebar)
      expect(commonSidebar.props.role).to.equal(role)
    })

    it('passes the total points possible to the common sidebar component', () => {
      testbed.render()
      const commonSidebar = testbed.findChildByType(CommonSidebar)
      expect(commonSidebar.props.totalPointsPossible).to.equal(4)
    })

    context('with a stimulus quizEntry', () => {
      const quizEntriesWithStimulus = quizEntries.set(-1, quizEntryE)

      it('renders a stimulus sidebar component', () => {
        testbed.render({quizEntries: quizEntriesWithStimulus})
        expect(testbed.findChildrenByType(Stimulus).length).to.eq(2)
      })
    })
  })

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