#!/usr/bin/env sh
# shellcheck disable=SC2034
dns_cloudns_info='ClouDNS.net
Site: ClouDNS.net
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cloudns
Options:
 CLOUDNS_AUTH_ID Regular auth ID
 CLOUDNS_SUB_AUTH_ID Sub auth ID
 CLOUDNS_AUTH_PASSWORD Auth Password
Author: Boyan Peychev <boyan@cloudns.net>
'

CLOUDNS_API="https://api.cloudns.net"
DOMAIN_TYPE=
DOMAIN_MASTER=

########  Public functions #####################

#Usage: dns_cloudns_add   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_cloudns_add() {
  _info "Using cloudns"

  if ! _dns_cloudns_init_check; then
    return 1
  fi

  zone="$(_dns_cloudns_get_zone_name "$1")"
  if [ -z "$zone" ]; then
    _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup."
    return 1
  fi

  host="$(echo "$1" | sed "s/\.$zone\$//")"
  record=$2

  _debug zone "$zone"
  _debug host "$host"
  _debug record "$record"

  _info "Adding the TXT record for $1"
  _dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60"
  if ! _contains "$response" "\"status\":\"Success\""; then
    _err "Record cannot be added."
    return 1
  fi
  _info "Added."

  return 0
}

#Usage: dns_cloudns_rm   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_cloudns_rm() {
  _info "Using cloudns"

  if ! _dns_cloudns_init_check; then
    return 1
  fi

  if [ -z "$zone" ]; then
    zone="$(_dns_cloudns_get_zone_name "$1")"
    if [ -z "$zone" ]; then
      _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup."
      return 1
    fi
  fi

  host="$(echo "$1" | sed "s/\.$zone\$//")"
  record=$2

  _dns_cloudns_get_zone_info "$zone"

  _debug "Type" "$DOMAIN_TYPE"
  _debug "Cloud Master" "$DOMAIN_MASTER"
  if _contains "$DOMAIN_TYPE" "cloud"; then
    zone=$DOMAIN_MASTER
  fi
  _debug "ZONE" "$zone"

  _dns_cloudns_http_api_call "dns/records.json" "domain-name=$zone&host=$host&type=TXT"
  if ! _contains "$response" "\"id\":"; then
    return 1
  fi

  for i in $(echo "$response" | tr '{' "\n" | grep -- "$record"); do
    record_id=$(echo "$i" | tr ',' "\n" | grep -E '^"id"' | sed -re 's/^\"id\"\:\"([0-9]+)\"$/\1/g')

    if [ -n "$record_id" ]; then
      _debug zone "$zone"
      _debug host "$host"
      _debug record "$record"
      _debug record_id "$record_id"

      _info "Deleting the TXT record for $1"
      _dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id"

      if ! _contains "$response" "\"status\":\"Success\""; then
        _err "The TXT record for $1 cannot be deleted."
      else
        _info "Deleted."
      fi
    fi
  done

  return 0
}

####################  Private functions below ##################################
_dns_cloudns_init_check() {
  if [ -n "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then
    return 0
  fi

  CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}"
  CLOUDNS_SUB_AUTH_ID="${CLOUDNS_SUB_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_SUB_AUTH_ID)}"
  CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}"
  if [ -z "$CLOUDNS_AUTH_ID$CLOUDNS_SUB_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then
    CLOUDNS_AUTH_ID=""
    CLOUDNS_SUB_AUTH_ID=""
    CLOUDNS_AUTH_PASSWORD=""
    _err "You don't specify cloudns api id and password yet."
    _err "Please create you id and password and try again."
    return 1
  fi

  if [ -z "$CLOUDNS_AUTH_ID" ] && [ -z "$CLOUDNS_SUB_AUTH_ID" ]; then
    _err "CLOUDNS_AUTH_ID or CLOUDNS_SUB_AUTH_ID is not configured"
    return 1
  fi

  if [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then
    _err "CLOUDNS_AUTH_PASSWORD is not configured"
    return 1
  fi

  _dns_cloudns_http_api_call "dns/login.json" ""

  if ! _contains "$response" "\"status\":\"Success\""; then
    _err "Invalid CLOUDNS_AUTH_ID or CLOUDNS_AUTH_PASSWORD. Server response: $response"
    return 1
  fi

  # save the api id and password to the account conf file.
  _saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID"
  _saveaccountconf_mutable CLOUDNS_SUB_AUTH_ID "$CLOUDNS_SUB_AUTH_ID"
  _saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD"

  CLOUDNS_INIT_CHECK_COMPLETED=1

  return 0
}

_dns_cloudns_get_zone_info() {
  zone=$1
  _dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zone"
  if ! _contains "$response" "\"status\":\"Failed\""; then
    DOMAIN_TYPE=$(echo "$response" | _egrep_o '"type":"[^"]*"' | cut -d : -f 2 | tr -d '"')
    if _contains "$DOMAIN_TYPE" "cloud"; then
      DOMAIN_MASTER=$(echo "$response" | _egrep_o '"cloud-master":"[^"]*"' | cut -d : -f 2 | tr -d '"')
    fi
  fi
  return 0
}

_dns_cloudns_get_zone_name() {
  i=2
  while true; do
    zoneForCheck=$(printf "%s" "$1" | cut -d . -f "$i"-100)

    if [ -z "$zoneForCheck" ]; then
      return 1
    fi

    _debug zoneForCheck "$zoneForCheck"

    _dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zoneForCheck"

    if ! _contains "$response" "\"status\":\"Failed\""; then
      echo "$zoneForCheck"
      return 0
    fi

    i=$(_math "$i" + 1)
  done
  return 1
}

_dns_cloudns_http_api_call() {
  method=$1

  _debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID"
  _debug CLOUDNS_SUB_AUTH_ID "$CLOUDNS_SUB_AUTH_ID"
  _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD"

  if [ -n "$CLOUDNS_SUB_AUTH_ID" ]; then
    auth_user="sub-auth-id=$CLOUDNS_SUB_AUTH_ID"
  else
    auth_user="auth-id=$CLOUDNS_AUTH_ID"
  fi

  encoded_password=$(echo "$CLOUDNS_AUTH_PASSWORD" | tr -d "\n\r" | _url_encode)
  if [ -z "$2" ]; then
    data="$auth_user&auth-password=$encoded_password"
  else
    data="$auth_user&auth-password=$encoded_password&$2"
  fi

  response="$(_get "$CLOUDNS_API/$method?$data")"

  _debug response "$response"

  return 0
}
