describe 'SelectPvr', ->
  Pvr = React.createFactory(require '../../src/components/pvr')
  SelectPvr = React.createFactory require('../../src/components/select_pvr')
  {Flux} = require 'delorean'
  isEqual = require 'lodash/isEqual'

  options = [
    {
      label: 'one'
      value: 1
      multiSelectGroupId: 100
    }
    {
      label: 'two'
      value: 2
      multiSelectGroupId: 100
    }
    {
      label: 'three'
      value: 3
      multiSelectGroupId: 101
    }
    {
      label: 'four'
      value: 4
      multiSelectGroupId: 102
    }
    {
      label: 'five'
      value: 5
      multiSelectGroupId: 102
    }
  ]

   
  #--------------------------------------------------------------------- Default Props
  it 'Should have default props', ->
    selectPvr = renderIntoDocument SelectPvr({
      close: ->
      onChange: ->
      pvrProps:
        anchor: document.createElement("div") 
    })
    
    defaultProps = selectPvr.props

    optionsTest = isEqual defaultProps.options, []
    stylesTest = isEqual defaultProps.styleMixin, {}

    expect(optionsTest).to.equal yes
    expect(stylesTest).to.equal yes
    expect(defaultProps.hideSelected).to.equal no
    expect(defaultProps.optionHeight).to.equal 36


  #--------------------------------------------------------------------- Sizing/Styling
  it 'Should resize itself to the number of options when height is auto', ->
    optionHeight = 100
    selectPvr = renderIntoDocument SelectPvr
      close: ->
      onChange: ->
      options: options
      optionHeight: optionHeight
      pvrProps:
       anchor: document.createElement("div") 
    
    node = ReactDOM.findDOMNode selectPvr 

    expect(node.style.height).to.equal("#{options.length * optionHeight + (options.length)}px")


  it 'Should adjust the auto height when hideSelected is on', ->
    optionHeight = 100
    selectPvr = renderIntoDocument SelectPvr
      close: ->
      onChange: ->
      options: options
      optionHeight: optionHeight
      hideSelected: yes
      pvrProps:
       anchor: document.createElement("div")
    
    node = ReactDOM.findDOMNode selectPvr 

    expect(node.style.height).to.equal("#{options.length * optionHeight + (options.length) - optionHeight}px")

  it 'Should use maxHeight if maxHeight is lower than calculated height (optionHeight * options.length)', ->
    optionHeight = 60
    selectPvr = renderIntoDocument SelectPvr
      close: ->
      onChange: ->
      options: options
      optionHeight: optionHeight
      maxHeight: 100
      pvrProps:
       anchor: document.createElement("div")
    
    node = ReactDOM.findDOMNode selectPvr 

    expect(node.style.height).to.equal('100px')
    

  it 'Should apply all styles passed in the styleMixin prop', ->
    styleMixin =
      left: '513px'
      top: '50%'

    selectPvr = renderIntoDocument SelectPvr
      close: ->
      onChange: ->
      options: options
      styleMixin: styleMixin
      pvrProps:
       anchor: document.createElement("div")
       width: '213px'
    
    node = ReactDOM.findDOMNode selectPvr 
    inner = node.getElementsByClassName('select-pvr')[0]

    expect(inner.style.left).to.equal(styleMixin.left)
    expect(inner.style.top).to.equal(styleMixin.top)
    expect(inner.style.width).to.equal('213px')

  #--------------------------------------------------------------------- Selection
  it 'Should set the selectedOptions state to the defaultSelected prop', ->
    selectPvr = renderIntoDocument SelectPvr
      close: ->
      onChange: ->
      options: options
      defaultSelected: options[3]
      pvrProps:
       anchor: document.createElement("div")
    
    expect(selectPvr.state.selectedOptions).to.equal(options[3])

  it 'Should apply the is-selected class to the defaultSelected option element', ->
    selectPvr = renderIntoDocument SelectPvr
      close: ->
      onChange: ->
      options: options
      defaultSelected: options[3]
      pvrProps:
       anchor: document.createElement("div")

    selectedEl = scryRenderedDOMComponentsWithClass selectPvr, 'is-selected'
    expect(selectedEl.length).to.equal(1)


  it 'Should NOT render the selected element when hideSelected is on', ->
    selectPvr = renderIntoDocument SelectPvr
      close: ->
      onChange: ->
      options: options
      defaultSelected: options[3]
      hideSelected: on
      pvrProps:
       anchor: document.createElement("div")

    optionsEls = scryRenderedDOMComponentsWithClass selectPvr, 'select-pvr-option'
    
    expect(optionsEls.length).to.equal(options.length - 1)

  it 'Should call the onChange prop when a non selected option is clicked', ->
    handleChange = sinon.spy()

    selectPvr = renderIntoDocument SelectPvr
      close: ->
      options: options
      defaultSelected: options[3]
      onChange: handleChange
      pvrProps:
       anchor: document.createElement("div")

    optionsEls = scryRenderedDOMComponentsWithClass selectPvr, 'select-pvr-option'

    Simulate.click optionsEls[1]

    expect(handleChange.calledWith(options[1])).to.equal(yes)


  it 'Should NOT call the onChange prop when a the selected option is clicked', ->
    handleChange = sinon.spy()

    selectPvr = renderIntoDocument SelectPvr
      close: ->
      options: options
      defaultSelected: options[3]
      onChange: handleChange
      pvrProps:
       anchor: document.createElement("div")

    optionsEls = scryRenderedDOMComponentsWithClass selectPvr, 'select-pvr-option'

    Simulate.click optionsEls[3]

    expect(handleChange.calledWith(options[3])).to.equal(no)

  it 'should fire onChange on selection, when multiSelect=true and there are NOT multiple multiSelectGroupIds of that value', ->
    handleChange = sinon.spy()

    selectPvr = renderIntoDocument SelectPvr
      close: ->
      options: options
      defaultSelected: options[1]
      onChange: handleChange
      multiSelect: true
      multiSelectKey: 'label'
      pvrProps:
       anchor: document.createElement("div")

    optionsEls = scryRenderedDOMComponentsWithClass selectPvr, 'select-pvr-option'
    Simulate.click optionsEls[2]

    assert.isTrue(handleChange.called)

  it 'should NOT fire onChange on selection, when multiSelect=true and there are multiple multiSelectGroupIds of that value', ->
    handleChange = sinon.spy()

    selectPvr = renderIntoDocument SelectPvr
      close: ->
      options: options
      defaultSelected: options[1]
      onChange: handleChange
      multiSelect: true
      multiSelectKey: 'label'
      pvrProps:
       anchor: document.createElement("div")

    optionsEls = scryRenderedDOMComponentsWithClass selectPvr, 'select-pvr-option'
    Simulate.click optionsEls[1]

    assert.isFalse(handleChange.called)

  it 'should fire onChange on unmount, when multiSelect=true', ->
    handleChange = sinon.spy()

    selectPvr = renderIntoDocument SelectPvr
      close: ->
      options: options
      defaultSelected: options[1]
      onChange: handleChange
      multiSelect: true
      multiSelectKey: 'label'
      pvrProps:
       anchor: document.createElement("div")

    optionsEls = scryRenderedDOMComponentsWithClass selectPvr, 'select-pvr-option'
    Simulate.click optionsEls[1]
    # add another selection
    Simulate.click optionsEls[2]

    # Unmount
    ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(selectPvr).parentNode)

    assert.equal(handleChange.lastCall.args[0], selectPvr.state.selectedOptions)

  it 'should only allow a single multiSelectGroupId to be selected, when multiSelect=true and multiSelectGroupId', ->
    handleChange = sinon.spy()

    selectPvr = renderIntoDocument SelectPvr
      close: ->
      options: options
      defaultSelected: options[0]
      onChange: handleChange
      multiSelect: true
      multiSelectKey: 'label'
      pvrProps:
       anchor: document.createElement("div")

    optionsEls = scryRenderedDOMComponentsWithClass selectPvr, 'select-pvr-option'

    # Initial selection
    Simulate.click optionsEls[0]
    # add another selection within that multiSelectGroupId
    Simulate.click optionsEls[1]
    # make sure that both are selected
    assert.equal(selectPvr.state.selectedOptions[options[0].label], options[0], 'keyed option 0 matches input')
    assert.equal(selectPvr.state.selectedOptions[options[1].label], options[1], 'keyed option 1 matches input')

    # select a new multiSelectGroupId
    Simulate.click optionsEls[2]
    # make sure the old ones are gone and the new one is selected
    assert.equal(Object.keys(selectPvr.state.selectedOptions).length, 1, 'old options gone')
    assert.equal(Object.keys(selectPvr.state.selectedOptions)[0], options[2].label, 'new option 2 selected')