$ = jQuery
context = window
context.JK ||= {};

context.JK.SiteValidator = class SiteValidator

  constructor: (site_type, success_callback, fail_callback, parent) ->
    @EVENTS = context.JK.EVENTS
    @rest = context.JK.Rest()
    @site_type = site_type
    @input_div = $(".site_validator."+site_type+"_validator", parent)
    @data_input = @input_div.find('input')

    @logger = context.JK.logger
    @spinner = @input_div.find('span.spinner-small')
    @checkmark = @input_div.find('.validate-checkmark')
    this.setSiteStatus(null)
    this.showFormatStatus()
    @is_rec_src = false
    @deferred_status_check = null
    @is_validating = false
    @success_callback = success_callback
    @fail_callback = fail_callback

  init: () =>
    this.renderErrors({})
    @spinner.hide()
    validator = this
    @data_input.on 'blur', ->
      validator.didBlur()
    @data_input.on 'focus', ->
      validator.showFormatStatus()
    @data_input.on 'change', ->
      @site_status = null

  dataToValidate: () =>
    url = @data_input.val()
    if url && 0 < url.length
      url.substring(0,2000)
    else
      null

  showFormatStatus: () =>
    data = this.dataToValidate()
    yn = true
    if data && ('url' == @site_type || @is_rec_src)
      regexp = /(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
      yn = regexp.test(this.dataToValidate())
      unless yn
        @checkmark.hide()
    yn

  didBlur: () =>
    if this.showFormatStatus()
      this.validateSite()

  validateSite: () =>
    unless data = this.dataToValidate()
      if @success_callback
        @success_callback(@input_div)
      return null
    this.setSiteStatus(null)
    @spinner.show()
    @rest.validateUrlSite(data, @site_type)
      .done(this.processSiteCheckSucceed)
      .fail(this.processSiteCheckFail)

  processSiteCheckSucceed: (response) =>
    @spinner.hide()

    if 'Valid Site' == response.message
      this.setSiteStatus(true)
      this.renderErrors({})
      if @deferred_status_check
        @deferred_status_check.resolve()
      if @success_callback
        @success_callback(@input_div)
    else
      this.setSiteStatus(false)
      this.renderErrors(response)
      if @deferred_status_check
        @deferred_status_check.reject()
      if @fail_callback
        @fail_callback(@input_div)

    @deferred_status_check = null
    @logger.debug("site_status = " + @site_status)

  processSiteCheckFail: (response) =>
    @logger.error("site check error")
    this.setSiteStatus(false)
    if @deferred_status_check
      @deferred_status_check.reject()
    @deferred_status_check = null

  setSiteStatus: (status) =>
    @site_status = status
    @spinner.hide()
    if true == status
      @checkmark.show()
    else
      @checkmark.hide()

  siteIsValid: () =>
    this.setSiteStatus(true)

  siteIsInvalid: () =>
    this.setSiteStatus(false)

  renderErrors: (errors) =>
    errdiv = @input_div.find('.error')
    if errmsg = context.JK.format_errors("site", errors)
      errdiv.show()
      errdiv.html(errmsg)
    else
      errdiv.hide()
      errdiv.html('')

  state: () =>
    dfr = $.Deferred()
    if null == @site_status
      @deferred_status_check = dfr
      this.validateSite()
    else
      if true == @site_status
         dfr.resolve()
      else
         dfr.reject()
    return dfr.promise()


context.JK.RecordingSourceValidator = class RecordingSourceValidator extends SiteValidator
  constructor: (site_type, success_callback, fail_callback, parent) ->
    super(site_type, success_callback, fail_callback, parent)
    @recording_sources = []
    @is_rec_src = true
    @add_btn = @input_div.find('a.add-recording-source')
    @site_success_callback = success_callback
    @site_fail_callback = fail_callback

  init: (sources) =>
    super()
    if sources
      @recording_sources = sources
    @add_btn.off('click').on 'click', =>
      this.attemptAdd()

  processSiteCheckSucceed: (response) =>
    super(response)
    @add_btn.removeClass('disabled')

    if @site_status
      @recording_sources.push({ url: response.data, recording_id: response.recording_id, recording_title: response.recording_title })
      if @site_success_callback
        @site_success_callback(@input_div)
    else
      if @site_fail_callback
        @site_fail_callback(@input_div)

  processSiteCheckFail: (response) =>
    super(response)
    @add_btn.removeClass('disabled')
    if @site_fail_callback
      @site_fail_callback(@input_div)

  didBlur: () =>
    # do nothing, validate on add only

  validateSite: () =>
    @add_btn.addClass('disabled')
    super()

  attemptAdd: () =>
    if data = this.dataToValidate()
      unless this.containsRecordingUrl(data)
        this.validateSite()

  removeRecordingId: (recording_id) =>
    start_len = @recording_sources.length
    @recording_sources = @recording_sources.filter (src) ->
      src["recording_id"] isnt recording_id.toString()
    start_len != @recording_sources.length

  containsRecordingUrl: (url) =>
    vals = $.grep @recording_sources, (src_data) ->
      src_data['url'] is url

    0 < vals.length

  recordingSources: () =>
    @recording_sources

