React = require 'react'
ReactDOM = require 'react-dom'
Spinner = React.createFactory(require('./spinner'))
FormValidation = require '../mixins/form_validation'
_ = require 'lodash'

{div, ul, button, input} = React.DOM

###
Input Props

@props.loading - OPTIONAL - Boolean
  indicator to determine that the input is loading a value from the server

@props.showClear - OPTIONAL - Boolean
  indicator to determine whether or not to show the clear "X" button 

@props.delayedActionOnChange - OPTIONAL - Object
  Takes action and interval parameters, will fire the action after the set interval everytime the componentWillReceiveProps method fires

@props.wrapperClass - OPTIONAL - String 
  class to be added to the wrpper div

@props.regexAllow - OPTIONAL - Array 
  runs the value through a regex test to see if it passes
###

TextInput = React.createClass
  
  displayName: 'TextInput'

  # Note - See form_validation for required props when using with this mixin
  mixins: [FormValidation]

  propTypes:
    type: React.PropTypes.string
    className: React.PropTypes.string
    regexAllow: React.PropTypes.object
    delayedActionOnChange: React.PropTypes.object
    tabIndex: React.PropTypes.number
    maxLength: React.PropTypes.number
    disabled: React.PropTypes.bool
    onChange: React.PropTypes.func
    onKeyDown: React.PropTypes.func
    onKeyUp: React.PropTypes.func
    onKeyPress: React.PropTypes.func
    style: React.PropTypes.object
    autoComplete: React.PropTypes.oneOfType [
      React.PropTypes.string
      React.PropTypes.bool
    ]
    placeholder: React.PropTypes.oneOfType [
      React.PropTypes.string
      React.PropTypes.number
    ]
    value: React.PropTypes.oneOfType [
      React.PropTypes.string
      React.PropTypes.number
    ]
    id: React.PropTypes.oneOfType [
      React.PropTypes.string
      React.PropTypes.number
    ]

  getInitialState: ->
    {
      value: @props.value or ''
    }

  getDefaultProps: -> 
    {
      type: 'text'
      loading: false
      className: 'text-input'
      wrapperClass: null
      showClear: false
      autoComplete: false
    }

  componentWillReceiveProps: (nextProps) ->
    {value} = nextProps

    if value? and value isnt @props.value
      @fireDelayedAction()
      @setState({ value: value })

  delayedActionTimer: null

  fireDelayedAction: ->
    {delayedActionOnChange} = @props

    if delayedActionOnChange?
      {action, interval} = delayedActionOnChange

      clearInterval(@delayedActionTimer)

      @delayedActionTimer = setTimeout =>
        action(@state.value)
      , interval

  render: ->
    {placeholder, tabIndex, className, maxLength, loading, type, showClear, onKeyDown, onKeyPress, wrapperClass, wrapperLabel, id, disabled, autoComplete, onBlur, style} = @props
    {value} = @state

    # Separate the false evaluations from the validation hash
    @getErrors()

    inputClass = className if className?
    inputClass += ' loading-spinner' if loading
    
    outerClass = 'field-wrap'
    outerClass += " #{wrapperClass}" if wrapperClass

    # Autocomplete
    autoComplete = switch typeof autoComplete 
      when 'string' then autoComplete
      when 'boolean'
        if autoComplete then 'on' else 'off'

    div {
      className: "#{outerClass} #{@invalidClass}"
      style: style
    }, [
      input {
        id: id
        className: inputClass
        ref: 'textInput'
        type: type
        placeholder: placeholder
        key: 'textInput'
        tabIndex: tabIndex
        value: value
        onChange: @handleChange
        onKeyDown: @onKeyDown
        onKeyUp: @handleKeyUp
        onKeyPress: onKeyPress
        onBlur: onBlur
        maxLength: maxLength
        spellCheck: false
        disabled: disabled
        autoComplete: autoComplete
      }
      div({
          key: 'input-spinner'
          className: 'input-spinner'
        }, 
          Spinner {
            length: 3
          }
      ) if loading
      button {
        className: 'search-clear'
        title: 'Clear Search'
        key: 'searchClearBtn'
        onClick: @clear
        tabIndex: -1
      }, [] if value.length > 0 and showClear
      div({
        className: 'field-errors-show'
        key: 'textInputErrorsShow'
      }, [
        div {
          className: 'field-errors'
          key: 'textInputErrors'
        }, 
          ul {
            className: 'field-errors-list'
          }, @validationErrors
      ]) if @validationErrors.length and not loading
    ]

  handleChange: (e) ->
    {value} = e.target
    {regexAllow, onChange} = @props

    # Check for disallowed chars
    if regexAllow? and value and not regexAllow.test(value) then return

    @setState {
      value: value
    }

    onChange?(e)

  onKeyDown: (e) ->
    e.preventDefault() if e.key is 'Enter'
    
    @props.onKeyDown?(e)  

  handleKeyUp: (e) ->
    if e.key is 'Enter'
      e.preventDefault() 
      @props.onEnterKey?(e)

    @props.onKeyUp?(e)

  getValue: ->
    @refs.textInput.value

  clear: ->
    @props.onChange(true)
    @setState({ value: '' })

  focus: ->
    ReactDOM.findDOMNode(@refs.textInput).focus()

  blur: ->
    ReactDOM.findDOMNode(@refs.textInput).blur()


module.exports = TextInput
