isEqual = require 'lodash/isEqual'
{makeGuid} = require '../utils'
{ENTER} = require '../constants/keyboard'
moment = require 'moment'

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
    
    value = if @getDateValue? then moment(@getDateValue()) else value

    @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
      groupId: @inputId
      isInPopover: isInPopover

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

    @validate(validation, value) 

    onChange?(@getValue(), jsonPath)
    @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, tabId} = @props
    if validationError?
      @context.addValidationError
        anchor: @refs.errorAnchor
        error: validationError
        groupId: @inputId
        isInPopover: isInPopover
        tabId: tabId
    else 
      @context.clearValidationError 
        groupId: @inputId
        isInPopover: 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, returnNull} = @props

    if @getDateValue? then return @getDateValue()

    value = do =>
      if @value? then @value
      else 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 ''

    if returnNull and value is '' then null else value

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

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

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

  handleErrorMouseOver: ->
    {isInPopover} = @props
    @context.toggleValidationError 
      groupId: @inputId
      status: on
      isInPopover: isInPopover

  handleErrorMouseOut: ->
    {isInPopover} = @props
    @context.toggleValidationError
      groupId: @inputId
      status: off
      isInPopover: isInPopover