/** @perf use const enums */
export enum DirectiveKind {
  Origin = '$ORIGIN',
  TimeToLive = '$TTL',
}

export const SUPPORTED_RECORD_TYPES = [
  'TXT',
  'NS',
  'A',
  'AAAA',
  'CNAME',
  'MX',
  'PTR',
  'SPF',
  'SRV',
  'CAA',
  'NAPTR',
] as const;

export const ALL_RECORD_TYPES = ['SOA', ...SUPPORTED_RECORD_TYPES] as const;

/** @private */
export const INSTRUCTION_TYPES = [
  ...SUPPORTED_RECORD_TYPES,
  DirectiveKind.TimeToLive as '$TTL',
  DirectiveKind.Origin as '$ORIGIN',
] as const;

export type RecordType = typeof SUPPORTED_RECORD_TYPES[number];

export type InstructionType = typeof INSTRUCTION_TYPES[number];

/** @perf const enum */
export enum RecordMinLengthKind {
  /**
   * treemonkey1.ca. 3W IN TXT "v=DKIM1\; k=rsa\; p=MIGf..."
   *                       TXT "eh=true"
   */
  TXT = 1,

  /**
   * www 1h IN CNAME \\008\\99.igloo.com.
   *           CNAME igloo.igloo.com.
   */
  CNAME = 1,

  /**
   * eh  1w   A 127.0.0.1
   * eh       A 127.0.0.1
   *          A 127.0.0.1
   */
  A = 1,

  /**
   * eh 3W AAAA  ::1
   * @     AAAA  ::1
   */
  AAAA = 1,

  /**
   * @  1W    NS   ns.igloo.com.
   * @        NS   NS2.NAMESERVER.NET.
   *    1W    NS   ns.igloo.com.
   */
  NS = 1,

  /**
   * 1       3W   PTR HOST1.igloo.com.
   * 10.3         PTR HOST3.igloo.com.
   * @            PTR HOST3.igloo.com.
   *              PTR HOST3.igloo.com.
   */
  PTR = 1,

  /**
   * igloo.com.  MX    10 mail.igloo.com.
   *             MX    10 mail.igloo.com.
   */
  MX = 2,

  /**
   * test1   3w   IN SPF   "v=spf2" "mx:gcloud-node.com." "-all"
   *                 SPF   "v=spf3" "mx:gcloud-node.com." "-all    "
   *                 SPF   "v=spf4" "mx:gcloud-node.com." "-all"
   *                 SPF   "v=spf4 mx:gcloud-node.com."
   */
  SPF = 1,

  /**
   * igloo.com       3W CAA 0 iodef "mailto:security@igloo.com"
   *                    CAA 0 iodef "mailto:security@igloo.com"
   */
  CAA = 3,

  /**
   * _foobar._tcp        SRV   0 1 9 old-slow-box.igloo.com.
   * _foobar._tcp   1W   SRV   0 1 9 old-slow-box.igloo.com.
   */
  SRV = 4,

  /**
   * rfc3403-1 86400 IN NAPTR 100 10 "u" "sip+E2U" "!^.*$!sip:information@foo.se!i" .
   *                          69 42  "u" "sip"     ".*"                             .
   */
  NAPTR = 6,

  /**
   * or 6 | 7...
   */
  SOA = 7,
}

/** @perf const enum */
export enum RecordMaxLengthKind {
  /**
   * @example           SPF    v=spf1  ip:4:192.168.0.1/16-all
   * @example           SPF    v=spf1  ip4:192.0.2.0/24 ip4:198.51.100.123 a -all
   */
  SPF = Infinity,
  SOA = Infinity,
  TXT = 1,
  CNAME = 1,
  A = 1,
  AAAA = 1,
  NS = 1,
  PTR = 1,
  MX = 2,
  CAA = 3,
  SRV = 4,
  NAPTR = 6,
}

/** @perf use numbers here in production & const enum */
export enum ErrorKeyKind {
  // === special ===
  /** api error, unused */
  Api = 'API',
  /** nothing in the input */
  EmptyInput = 'EMPTY',
  /** nothing to create */
  NoRecords = 'NO_RECORDS_TO_CREATE',
  /** we have records, but none are valid */
  NoValidRecords = 'NO_VALID_RECORDS_TO_CREATE',
  /** not standard */
  BadDirective = 'BAD_DIRECTIVE',
  /** exists either in already created records or twice here */
  Duplicated = 'DUPLICATED',
  /** unknown */
  Unknown = 'UNKNOWN',
  /** fallback case */
  Missing = '',

  // === ttl ===
  /** Invalid ttl format */
  TtlInvalidFormat = 'TTL_INVALID_FORMAT',
  /** Value too large */
  TtlOverflow = 'TTL_OVERFLOW',
  /** Invalid format & missing default value as a number */
  TtlMissingDefault = 'TTL_INVALID_FORMAT_MISSING_DEFAULT',

  // === args ===
  /** wrong number of args for this instruction */
  WrongLength = 'WRONG_LENGTH',
  /** format of an instruction is wrong */
  WrongNameArgsLength = 'EXTRA_NAME_TTL_ARGS',
}

export const ERROR_KEYS = [
  ErrorKeyKind.Api,
  ErrorKeyKind.EmptyInput,
  ErrorKeyKind.NoRecords,
  ErrorKeyKind.NoValidRecords,
  ErrorKeyKind.BadDirective,
  ErrorKeyKind.TtlInvalidFormat,
  ErrorKeyKind.TtlOverflow,
  ErrorKeyKind.TtlMissingDefault,
  ErrorKeyKind.WrongLength,
  ErrorKeyKind.WrongNameArgsLength,
  ErrorKeyKind.Duplicated,
  ErrorKeyKind.Unknown,
] as const;

/** @idea move `warnings` to `errors` and make => `problems` + `severity` */
export enum WarningKeyKind {
  NsIgnored = 'SOA_IGNORED',
  SoaIgnored = 'NS_IGNORED',
}

export type TtlErrorKeyType =
  | ErrorKeyKind.TtlInvalidFormat
  | ErrorKeyKind.TtlMissingDefault
  | ErrorKeyKind.TtlOverflow;
