/**
  RFC 1035 https://datatracker.ietf.org/doc/html/rfc1035  

  <domain> ::= <subdomain> | " "  
  <subdomain> ::= <label> | <subdomain> "." <label>  
  <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]  
  <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>  
  <let-dig-hyp> ::= <let-dig> | "-"  
  <let-dig> ::= <letter> | <digit>  
  <letter> ::= any one of the 52 alphabetic characters A through Z in
  upper case and a through z in lower case  
  <digit> ::= any one of the ten digits 0 through 9  
 
  Note that while upper and lower case letters are allowed in domain
  names, no significance is attached to the case.  That is, two names with
  the same spelling but different case are to be treated as if identical.

  The labels must follow the rules for ARPANET host names.  They must
  start with a letter, end with a letter or digit, and have as interior
  characters only letters, digits, and hyphen.  There are also some
  restrictions on the length.  Labels must be 63 characters or less.

  For example, the following strings identify hosts in the Internet:

  A.ISI.EDU XX.LCS.MIT.EDU SRI-NIC.ARPA
 */
const MAX_LABEL_LENGTH = 63;
const REGEXP = {
  LOWERCASE_LETTERS_OR_NUMBERS_OR_HYPHENS_ONLY: /^[a-z0-9-]*$/,
  STARTS_WITH_NUMBER: /^[0-9]/,
  STARTS_WITH_HYPHEN: /^-/,
  ENDS_WITH_HYPHEN: /-$/,
};

export function isValidDomainName(value: string): boolean {
  if (!value) {
    return false;
  }
  const labels = value.split(".");
  if (labels.length < 2) {
    return false;
  }

  if (labels.some((label) => !isValidLabel(label))) {
    return false;
  }

  return true;
}

function isValidLabel(value: string): boolean {
  if (value.length < 1) {
    return false;
  }
  if (value.length > MAX_LABEL_LENGTH) {
    return false;
  }

  if (!REGEXP.LOWERCASE_LETTERS_OR_NUMBERS_OR_HYPHENS_ONLY.test(value)) {
    return false;
  }

  if (REGEXP.STARTS_WITH_HYPHEN.test(value)) {
    return false;
  }

  if (REGEXP.ENDS_WITH_HYPHEN.test(value)) {
    return false;
  }

  return true;
}
