ReactDOM = require 'react-dom'
_ = require 'lodash'
{makeGuid} = require '../utils'
{ENTER} = require '../constants/keyboard'

module.exports =

  getInitialState: ->
    valueHasChanged: no
  
  componentWillMount: -> 
    # create a unique id for this input
    # used by the validation framework to group validation errors
    @inputId = makeGuid()

  componentDidMount: ->
    {value, validation, focusOnMount} = @props
    
    @validate validation, value
    
    # Focus
    if focusOnMount then @focus()
    

  componentWillReceiveProps: (nextProps) ->
    {value, validation} = nextProps
    
    validationChanged = (
      if typeof validation is 'function' then no
      else not _.isEqual(validation?.messages, @props.validation?.messages)
    )

    # Run validaiton if the validation changes
    if validationChanged then @validate(validation, value) 

  
  componentWillUnmount: -> 
    {isInPopover} = @props

    @context.clearValidationError(@inputId, isInPopover)

  handleChange: (e) ->
    {value} = e.target
    {onChange, validation} = @props
    
    {valueHasChanged} = @state
    @setState {valueHasChanged: yes} if not valueHasChanged

    @validate(validation, value) 
    onChange?(value)
    @fireDelayedAction()

  fireDelayedAction: ->
    {delayedActionOnChange, value} = @props

    if delayedActionOnChange?
      {action, interval} = delayedActionOnChange

      clearInterval(@delayedActionTimer)

      @delayedActionTimer = setTimeout =>
        action(value)
      , interval
  
  validate: (validation, value) ->
    return if validation is off 

    # Run validation and show any auto show messages
    if typeof validation is 'function' then validationError = validation(value)
    # validation can also be passed as a static array
    else validationError = validation

    {isInPopover} = @props
    if validationError?
      @context.addValidationError(@refs.errorAnchor, validationError, @inputId, isInPopover)
    else 
      @context.clearValidationError @inputId, isInPopover
      

  handleKeyUp: (e) ->
    {onEnterKey, onKeyUp} = @props

    # If there's an enter key handler, fire it
    if e.keyCode is ENTER then onEnterKey?(e)

    # Fire for all other keyup events
    onKeyUp?(e)

  getValue: -> 
    {returnFullObjects, textTransform, options, valueField} = @props

    value = do =>
      if @refs.input.getValue? then @refs.input.getValue()
      else @refs.input.value

    # Run the input through any text transforms before returning
    if textTransform? and value
      value = textTransform value

    if returnFullObjects
      valueField = valueField or 'value'
      for item in options when item[valueField] is value
        valueObj = item 
        break

      return valueObj or null

    value

  getTextareaValue: -> 
    value = do =>
      if @refs.textarea.getValue? then @refs.textarea.getValue()
      else @refs.textarea.value

    # Run the textarea through any text transforms before returning
    if @props.textTransform? and value
      value = @props.textTransform(value)

    return value

  clear: -> @props.onChange('')

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

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

  handleErrorMouseOver: ->
    {isInPopover} = @props
    @context.toggleValidationError @inputId, yes, isInPopover

  handleErrorMouseOut: ->
    {isInPopover} = @props
    @context.toggleValidationError @inputId, no, isInPopover