<commit_before>ServiceManager = require './ServiceManager.coffee'
{race}         = require 'bongo'

splitDomain = (domainName) ->
  splitted  = domainName.split "."
  return {
    domain    : splitted[0]
    extension : if splitted.length > 1 then splitted[1..].join "." else ""
  }

module.exports = class DomainService extends ServiceManager

  request = require 'request'

  # TODO : nameservers should change according to koding.com NS
  # nameservers = ["ns29.domaincontrol.in","ns30.domaincontrol.in"]
  nameservers = [
    "sina482303.mercury.orderbox-dns.com",
    "sina482303.venus.orderbox-dns.com",
    "sina482303.earth.orderbox-dns.com",
    "sina482303.mars.orderbox-dns.com"
  ]

  prices        = {} # Prices will be updated with first request
  availableTLDs = [
    "com","net","org","co","me"
    "info","in","ca","us","ru"
    "ws","eu","cn","cc","biz"
  ]

  getAvailableTlds: (callback=->)-> callback availableTLDs

  getDomainInfo: (domainName, callback)->

    {domain, extension} = splitDomain domainName

    if extension not in availableTLDs
      return callback "Tld is blank or not supported", null

    options =
      action          : "available"
      service         : "domains"
      parameters      :
        tlds          : extension
        "domain-name" : domain

    @makeRequestToResellerApi options, (err, res)=>
      return callback err if err
      available = res[domainName]?.status is 'available'
      if not available then callback err, {available}
      else
        @getTldPrice extension, (err, price)->
          return callback err, {available}  if err
          callback err, {available, price}

  getDomainSuggestions: (domainName, callback) ->
    suggestions = []

    attachPrice = race (i, {domain, extension}, fin) =>
      @getTldPrice extension, (err, price) ->
        return callback err, null  if err
        suggestions.push {domain, price}
        fin()
    , ->
      return callback null, suggestions

    {domain, extension} = splitDomain domainName

    @makeSuggestionRequestToDomainr domain, (err, suggestionResponse)->
      return callback err, suggestions  if err

      if suggestionResponse.results.length is 0
        return callback null, suggestions

      for result in suggestionResponse.results
        if result.availability is 'available'
          {domain, extension} = splitDomain result.domain
          if extension in availableTLDs and result.domain isnt domainName
            attachPrice {domain:result.domain, extension}
            foundASuggestion = yes

      unless foundASuggestion
        callback null, suggestions

  getTldPrice: (tld, callback) ->
    if prices[tld]? then callback null, prices[tld]
    else @getTldPrices (err, prices) ->
      return callback err, null  if err
      callback null, prices[tld]

  getTldPrices: (callback) ->

    options =
      service    : "products"
      action     : "reseller-price"
      parameters : resellerid : @authUserId

    @makeRequestToResellerApi options, (err, apiResponseBody) =>
      return callback err, null  if err
      priceList = {}
      for key, value of apiResponseBody
        # TODO (1) tld parsing is not so easy :(
        # This logic needs to be extended when new domains are added to
        # the support list
        currentTld = key.match(/^do[mt]([a-z]+)$/)?[1]
        if key is "domcno" # com is named domcno
          priceList["com"] = value[0].pricing.addnewdomain[1]
        else if currentTld and (currentTld in availableTLDs)
          priceList[currentTld] = value[0].pricing.addnewdomain[1]

      # TODO: Invalidate this prices information after sometime.
      DomainService.prices = priceList
      return callback null, priceList


  registerDomain: (domainInfo, callback)->
    #invoice option may change, but for now NoInvoice parameter is given,
    params =
      "domain-name"        : domainInfo.domainName
      "years"              : domainInfo.years
      "ns"                 : nameservers
      "customer-id"        : domainInfo.customerId
      "reg-contact-id"     : domainInfo.regContactId
      "admin-contact-id"   : domainInfo.adminContactId
      "tech-contact-id"    : domainInfo.techContactId
      "billing-contact-id" : domainInfo.billingContactId
      "invoice-option"     : domainInfo.invoiceOption
      "protect-privacy"    : domainInfo.protectPrivacy

    options =
      service              : "domains"
      action               : "register"
      parameters           : params

    @makeRequestToResellerApi options, callback

  fetchProxyFilters:(callback)->


  createProxyFilter:(params, callback)->
    options =
      method  : 'POST'
      uri     : "http://kontrol.in.koding.com/filters/#{params.filterInfo.name}"
      body    : JSON.stringify params.filterInfo

      headers : {'content-type': 'application/json'}

    request.post options, (error, response, body)=>
      @_returnResponse error, response, body, callback

  fetchProxyRules:(domainName, callback)->
    options =
      uri : "http://kontrol.in.koding.com/restrictions/#{domainName}"

    request.get options, (error, response, body)=>
      @_returnResponse error, response, body, callback

  createProxyRule: (params, callback)->
    options =
      method : 'POST'
      uri    : "http://kontrol.in.koding.com/restrictions/#{params.domainName}/list/#{params.ruleName}"
      body   : JSON.stringify params.behaviorInfo

    request.post options, (error, response, body)=>
      @_returnResponse error, response, body, callback

  deleteProxyRule: (params, callback)->
    options =<commit_msg>Sample method call added for future use of reseller's suggestion API since domai.nr returns wrong availability states for domains. No need to send resellerId since we are covering it already.<commit_after>ServiceManager = require './ServiceManager.coffee'
{race}         = require 'bongo'

splitDomain = (domainName) ->
  splitted  = domainName.split "."
  return {
    domain    : splitted[0]
    extension : if splitted.length > 1 then splitted[1..].join "." else ""
  }

module.exports = class DomainService extends ServiceManager

  request = require 'request'

  # TODO : nameservers should change according to koding.com NS
  # nameservers = ["ns29.domaincontrol.in","ns30.domaincontrol.in"]
  nameservers = [
    "sina482303.mercury.orderbox-dns.com",
    "sina482303.venus.orderbox-dns.com",
    "sina482303.earth.orderbox-dns.com",
    "sina482303.mars.orderbox-dns.com"
  ]

  prices        = {} # Prices will be updated with first request
  availableTLDs = [
    "com","net","org","co","me"
    "info","in","ca","us","ru"
    "ws","eu","cn","cc","biz"
  ]

  getAvailableTlds: (callback=->)-> callback availableTLDs

  getDomainInfo: (domainName, callback)->

    {domain, extension} = splitDomain domainName

    if extension not in availableTLDs
      return callback "Tld is blank or not supported", null

    options =
      service         : "domains"
      action          : "available"
      parameters      :
        tlds          : extension
        "domain-name" : domain

    @makeRequestToResellerApi options, (err, res)=>
      return callback err if err
      available = res[domainName]?.status is 'available'
      if not available then callback err, {available}
      else
        @getTldPrice extension, (err, price)->
          return callback err, {available}  if err
          callback err, {available, price}

  getDomainSuggestions: (domainName, callback) ->
    suggestions = []

    attachPrice = race (i, {domain, extension}, fin) =>
      @getTldPrice extension, (err, price) ->
        return callback err, null  if err
        suggestions.push {domain, price}
        fin()
    , ->
      return callback null, suggestions

    {domain, extension} = splitDomain domainName

    # Following is added for using Reseller's suggestion
    # Use it if domai.nr becames useless. ~ GG

    # options =
    #   service           : "domains"
    #   action            : "suggest-names"
    #   parameters        :
    #     keyword         : domain
    #     tlds            : extension
    #     'no-of-results' : 5
    #     'add-related'   : yes

    # @makeRequestToResellerApi options, (err, suggestionResponse)->
    #   return callback err, suggestions  if err

    #   suggestedNames = Object.keys(suggestionResponse)
    #   if suggestedNames.length is 0
    #     return callback null, suggestions

    #   for own domain, status of suggestionResponse
    #     if status[extension] is 'available'
    #       if extension in availableTLDs # and domain isnt domainName
    #         attachPrice {domain:"#{domain}.#{extension}", extension}
    #         foundASuggestion = yes

    #   unless foundASuggestion
    #     callback null, suggestions

    @makeSuggestionRequestToDomainr domain, (err, suggestionResponse)->
      return callback err, suggestions  if err

      if suggestionResponse.results.length is 0
        return callback null, suggestions

      for result in suggestionResponse.results
        if result.availability is 'available'
          {domain, extension} = splitDomain result.domain
          if extension in availableTLDs and result.domain isnt domainName
            attachPrice {domain:result.domain, extension}
            foundASuggestion = yes

      unless foundASuggestion
        callback null, suggestions

  getTldPrice: (tld, callback) ->
    if prices[tld]? then callback null, prices[tld]
    else @getTldPrices (err, prices) ->
      return callback err, null  if err
      callback null, prices[tld]

  getTldPrices: (callback) ->

    options =
      service    : "products"
      action     : "reseller-price"

    @makeRequestToResellerApi options, (err, apiResponseBody) =>
      return callback err, null  if err
      priceList = {}
      for key, value of apiResponseBody
        # TODO (1) tld parsing is not so easy :(
        # This logic needs to be extended when new domains are added to
        # the support list
        currentTld = key.match(/^do[mt]([a-z]+)$/)?[1]
        if key is "domcno" # com is named domcno
          priceList["com"] = value[0].pricing.addnewdomain[1]
        else if currentTld and (currentTld in availableTLDs)
          priceList[currentTld] = value[0].pricing.addnewdomain[1]

      # TODO: Invalidate this prices information after sometime.
      DomainService.prices = priceList
      return callback null, priceList


  registerDomain: (domainInfo, callback)->
    #invoice option may change, but for now NoInvoice parameter is given,
    params =
      "domain-name"        : domainInfo.domainName
      "years"              : domainInfo.years
      "ns"                 : nameservers
      "customer-id"        : domainInfo.customerId
      "reg-contact-id"     : domainInfo.regContactId
      "admin-contact-id"   : domainInfo.adminContactId
      "tech-contact-id"    : domainInfo.techContactId
      "billing-contact-id" : domainInfo.billingContactId
      "invoice-option"     : domainInfo.invoiceOption
      "protect-privacy"    : domainInfo.protectPrivacy

    options =
      service              : "domains"
      action               : "register"
      parameters           : params

    @makeRequestToResellerApi options, callback

  fetchProxyFilters:(callback)->

  createProxyFilter:(params, callback)->
    options =
      method  : 'POST'
      uri     : "http://kontrol.in.koding.com/filters/#{params.filterInfo.name}"
      body    : JSON.stringify params.filterInfo

      headers : {'content-type': 'application/json'}

    request.post options, (error, response, body)=>
      @_returnResponse error, response, body, callback

  fetchProxyRules:(domainName, callback)->
    options =
      uri : "http://kontrol.in.koding.com/restrictions/#{domainName}"

    request.get options, (error, response, body)=>
      @_returnResponse error, response, body, callback

  createProxyRule: (params, callback)->
    options =
      method : 'POST'
      uri    : "http://kontrol.in.koding.com/restrictions/#{params.domainName}/list/#{params.ruleName}"
      body   : JSON.stringify params.behaviorInfo

    request.post options, (error, response, body)=>
      @_returnResponse error, response, body, callback

  deleteProxyRule: (params, callback)->
    options =
{'fraction_non_alphanumeric': 0.10349309504467913, 'fraction_numerical': 0.006336311941510966, 'mean_word_length': 2.624080070650574, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 54, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6888048', 'n_tokens_mistral': 3623, 'n_tokens_neox': 3463, 'n_words': 940}