import { fromJS, is, Map } from 'immutable'
import SessionItem from '../SessionItem'
import SessionItemResult from '../SessionItemResult'
import Stimulus from '../Stimulus'
import Item from '../Item'

import { setFakeStore, unsetFakeStore } from '../../../reduxStore'

import {
  defaultChecks
} from '../../../../tests/util/recordTests'

describe('SessionItem Record', () => {
  describe('#constructor', () => {
    const defaultsToCheck = {item: {}}
    defaultChecks(SessionItem, defaultsToCheck)
  })

  describe('#getItem', () => {
    it('returns an item using the data in the "item" key', () => {
      const itemData = {id: '2', itemBody: 'foo'}
      const sessionItem = new SessionItem({item: itemData})
      const expectedItem = new Item(itemData, {})
      expect(is(sessionItem.getItem(), expectedItem)).to.be.true()
    })
  })

  describe('#sessionItemResult', () => {
    const fakeState = fromJS({
      sessionItems: {
        '10_1': { id: '10_1' }
      },
      sessionItemResults: {
        '10_1': { id: '10_1' }
      }
    })

    before(() => {
      setFakeStore(fakeState)
    })

    after(() => {
      unsetFakeStore()
    })

    it('returns the associated sessionItem', () => {
      const si = new SessionItem({id: '10_1'})
      expect(si.sessionItemResult.id).to.eq(new SessionItemResult({id: '10_1'}).id)
    })

    it('returns an empty SessionItemResult if not found', () => {
      const si = new SessionItem({id: '10_2'})
      expect(si.sessionItemResult.id).to.eq(new SessionItemResult().id)
    })
  })

  describe('#type', () => {
    it('returns Stimulus if stimulus is not null', () => {
      const si = new SessionItem({stimulus: {id: '1'}})
      expect(si.type).to.eq('Stimulus')
    })

    it('returns Item if stimulus is null', () => {
      const si = new SessionItem()
      expect(si.type).to.eq('Item')
    })
  })

  describe('#isStimulus', () => {
    it('returns true if stimulus is not null', () => {
      const si = new SessionItem({stimulus: {id: '1'}})
      expect(si.isStimulus).to.be.true()
    })

    it('returns false if stimulus is null', () => {
      const si = new SessionItem()
      expect(si.isStimulus).to.be.false()
    })
  })

  describe('#stimulusRecord', () => {
    it('returns a Stimulus record', () => {
      const si = new SessionItem()
      expect(si.stimulusRecord).to.be.instanceOf(Stimulus)
    })

    it('returns a Stimulus record with the data from the sessionItem', () => {
      const si = new SessionItem({stimulus: {id: '1'}})
      expect(si.stimulusRecord.id).to.eq('1')
    })
  })

  describe('#hasNestedRecords', () => {
    it('returns true if stimulus', () => {
      const si = new SessionItem({stimulus: Map({id: '1'})})
      expect(si.hasNestedRecords).to.be.true()
    })

    it('returns false if not stimulus', () => {
      const si = new SessionItem()
      expect(si.hasNestedRecords).to.be.false()
    })
  })

  describe('#positionSlots', () => {
    const fakeState = fromJS({
      sessionItems: {
        1: { id: '1', stimulusKey: '1', quizSessionId: '1' },
        2: { id: '2', stimulusKey: '1', quizSessionId: '1' },
        4: { id: '4', stimulusKey: '1', quizSessionId: '1' },
        3: { id: '3' }
      }
    })

    before(() => {
      setFakeStore(fakeState)
    })

    after(() => {
      unsetFakeStore()
    })

    it('returns 0 if not a stimulus', () => {
      const si = new SessionItem()
      expect(si.positionSlots).to.eq(0)
    })

    it('returns the number of items minus 1 if a stimulus', () => {
      const si = new SessionItem({stimulus: {}, stimulusKey: '1', quizSessionId: '1'})
      expect(si.positionSlots).to.eq(2)
    })

    it('returns 0 if an empty stimulus', () => {
      const si = new SessionItem({stimulus: {}, stimulusKey: '100', quizSessionId: '1'})
      expect(si.positionSlots).to.eq(0)
    })
  })

  describe('#displayPositionSlots', () => {
    const fakeState = fromJS({
      sessionItems: {
        1: { id: '1', stimulusKey: '1', quizSessionId: '1' },
        2: { id: '2', stimulusKey: '1', quizSessionId: '1' },
        3: { id: '3' }
      }
    })

    before(() => {
      setFakeStore(fakeState)
    })

    after(() => {
      unsetFakeStore()
    })

    it('returns 1 if not a stimulus', () => {
      const si = new SessionItem({type: 'Item'})
      expect(si.displayPositionSlots).to.eq(1)
    })

    it('returns number of nested items in the stimulus', () => {
      const si = new SessionItem({stimulus: {}, stimulusKey: '1', quizSessionId: '1'})
      expect(si.displayPositionSlots).to.eq(2)
    })
  })

  describe('#getNestedEntries', () => {
    const fakeState = fromJS({
      sessionItems: {
        1: { id: '1', stimulus: {id: '2'}, stimulusKey: '1', quizSessionId: '1' },
        2: { id: '2', stimulus: {id: '2'}, stimulusKey: '1', quizSessionId: '1' },
        3: { id: '3', quizSessionId: '2' },
        4: { id: '4', stimulus: {id: '2'}, stimulusKey: '1', quizSessionId: '2' },
        5: { id: '5', stimulus: {id: '2'}, stimulusKey: '1', quizSessionId: '2' }
      }
    })

    before(() => {
      setFakeStore(fakeState)
    })

    after(() => {
      unsetFakeStore()
    })

    it('returns all the SessionItems that have the same stimulusKey and quizSessionId', () => {
      const si = new SessionItem({stimulus: {}, stimulusKey: '1', quizSessionId: '1'})
      expect(si.getNestedEntries().size).to.eq(2)
    })

    it('falls back to use the stimulus id when stimulusKey is not present', () => {
      const si = new SessionItem({stimulus: Map({id: '2'}), quizSessionId: '1'})
      expect(si.getNestedEntries().size).to.eq(2)
    })
  })
})
