/* eslint-disable prefer-destructuring */
/* eslint-disable no-param-reassign */

import * as common from './common';
import * as constants4 from './v4/constants';
import * as constants6 from './v6/constants';
import * as helpers from './v6/helpers';
import { Address4 } from './ipv4';
import {
  ADDRESS_BOUNDARY,
  possibleElisions,
  simpleRegularExpression,
} from './v6/regular-expressions';
import { AddressError } from './address-error';
import { testBit } from './common';

function assert(condition: any): asserts condition {
  if (!condition) {
    throw new Error('Assertion failed.');
  }
}

function addCommas(number: string): string {
  const r = /(\d+)(\d{3})/;

  while (r.test(number)) {
    number = number.replace(r, '$1,$2');
  }

  return number;
}

function spanLeadingZeroes4(n: string): string {
  n = n.replace(/^(0{1,})([1-9]+)$/, '<span class="parse-error">$1</span>$2');
  n = n.replace(/^(0{1,})(0)$/, '<span class="parse-error">$1</span>$2');

  return n;
}

/*
 * A helper function to compact an array
 */
function compact(address: string[], slice: number[]) {
  const s1 = [];
  const s2 = [];
  let i;

  for (i = 0; i < address.length; i++) {
    if (i < slice[0]) {
      s1.push(address[i]);
    } else if (i > slice[1]) {
      s2.push(address[i]);
    }
  }

  return s1.concat(['compact']).concat(s2);
}

function paddedHex(octet: string): string {
  return parseInt(octet, 16).toString(16).padStart(4, '0');
}

function unsignByte(b: number) {
  // eslint-disable-next-line no-bitwise
  return b & 0xff;
}

interface SixToFourProperties {
  prefix: string;
  gateway: string;
}

interface TeredoProperties {
  prefix: string;
  server4: string;
  client4: string;
  flags: string;
  coneNat: boolean;
  microsoft: {
    reserved: boolean;
    universalLocal: boolean;
    groupIndividual: boolean;
    nonce: string;
  };
  udpPort: string;
}

/**
 * Represents an IPv6 address
 * @class Address6
 * @param {string} address - An IPv6 address string
 * @param {number} [groups=8] - How many octets to parse
 * @example
 * var address = new Address6('2001::/32');
 */
export class Address6 {
  address4?: Address4;
  address: string;
  addressMinusSuffix: string = '';
  elidedGroups?: number;
  elisionBegin?: number;
  elisionEnd?: number;
  groups: number;
  parsedAddress4?: string;
  parsedAddress: string[];
  parsedSubnet: string = '';
  subnet: string = '/128';
  subnetMask: number = 128;
  v4: boolean = false;
  zone: string = '';

  constructor(address: string, optionalGroups?: number) {
    if (optionalGroups === undefined) {
      this.groups = constants6.GROUPS;
    } else {
      this.groups = optionalGroups;
    }

    this.address = address;

    const subnet = constants6.RE_SUBNET_STRING.exec(address);

    if (subnet) {
      this.parsedSubnet = subnet[0].replace('/', '');
      this.subnetMask = parseInt(this.parsedSubnet, 10);
      this.subnet = `/${this.subnetMask}`;

      if (
        Number.isNaN(this.subnetMask) ||
        this.subnetMask < 0 ||
        this.subnetMask > constants6.BITS
      ) {
        throw new AddressError('Invalid subnet mask.');
      }

      address = address.replace(constants6.RE_SUBNET_STRING, '');
    } else if (/\//.test(address)) {
      throw new AddressError('Invalid subnet mask.');
    }

    const zone = constants6.RE_ZONE_STRING.exec(address);

    if (zone) {
      this.zone = zone[0];

      address = address.replace(constants6.RE_ZONE_STRING, '');
    }

    this.addressMinusSuffix = address;

    this.parsedAddress = this.parse(this.addressMinusSuffix);
  }

  static isValid(address: string): boolean {
    try {
      // eslint-disable-next-line no-new
      new Address6(address);

      return true;
    } catch (e) {
      return false;
    }
  }

  /**
   * Convert a BigInt to a v6 address object
   * @memberof Address6
   * @static
   * @param {bigint} bigInt - a BigInt to convert
   * @returns {Address6}
   * @example
   * var bigInt = BigInt('1000000000000');
   * var address = Address6.fromBigInt(bigInt);
   * address.correctForm(); // '::e8:d4a5:1000'
   */
  static fromBigInt(bigInt: bigint): Address6 {
    const hex = bigInt.toString(16).padStart(32, '0');
    const groups = [];
    let i;

    for (i = 0; i < constants6.GROUPS; i++) {
      groups.push(hex.slice(i * 4, (i + 1) * 4));
    }

    return new Address6(groups.join(':'));
  }

  /**
   * Convert a URL (with optional port number) to an address object
   * @memberof Address6
   * @static
   * @param {string} url - a URL with optional port number
   * @example
   * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/');
   * addressAndPort.address.correctForm(); // 'ffff::'
   * addressAndPort.port; // 8080
   */
  static fromURL(url: string) {
    let host: string;
    let port: string | number | null = null;
    let result: string[] | null;

    // If we have brackets parse them and find a port
    if (url.indexOf('[') !== -1 && url.indexOf(']:') !== -1) {
      result = constants6.RE_URL_WITH_PORT.exec(url);

      if (result === null) {
        return {
          error: 'failed to parse address with port',
          address: null,
          port: null,
        };
      }

      host = result[1];
      port = result[2];
      // If there's a URL extract the address
    } else if (url.indexOf('/') !== -1) {
      // Remove the protocol prefix
      url = url.replace(/^[a-z0-9]+:\/\//, '');

      // Parse the address
      result = constants6.RE_URL.exec(url);

      if (result === null) {
        return {
          error: 'failed to parse address from URL',
          address: null,
          port: null,
        };
      }

      host = result[1];
      // Otherwise just assign the URL to the host and let the library parse it
    } else {
      host = url;
    }

    // If there's a port convert it to an integer
    if (port) {
      port = parseInt(port, 10);

      // squelch out of range ports
      if (port < 0 || port > 65536) {
        port = null;
      }
    } else {
      // Standardize `undefined` to `null`
      port = null;
    }

    return {
      address: new Address6(host),
      port,
    };
  }

  /**
   * Create an IPv6-mapped address given an IPv4 address
   * @memberof Address6
   * @static
   * @param {string} address - An IPv4 address string
   * @returns {Address6}
   * @example
   * var address = Address6.fromAddress4('192.168.0.1');
   * address.correctForm(); // '::ffff:c0a8:1'
   * address.to4in6(); // '::ffff:192.168.0.1'
   */
  static fromAddress4(address: string): Address6 {
    const address4 = new Address4(address);

    const mask6 = constants6.BITS - (constants4.BITS - address4.subnetMask);

    return new Address6(`::ffff:${address4.correctForm()}/${mask6}`);
  }

  /**
   * Return an address from ip6.arpa form
   * @memberof Address6
   * @static
   * @param {string} arpaFormAddress - an 'ip6.arpa' form address
   * @returns {Adress6}
   * @example
   * var address = Address6.fromArpa(e.f.f.f.3.c.2.6.f.f.f.e.6.6.8.e.1.0.6.7.9.4.e.c.0.0.0.0.1.0.0.2.ip6.arpa.)
   * address.correctForm(); // '2001:0:ce49:7601:e866:efff:62c3:fffe'
   */
  static fromArpa(arpaFormAddress: string): Address6 {
    // remove ending ".ip6.arpa." or just "."
    let address = arpaFormAddress.replace(/(\.ip6\.arpa)?\.$/, '');
    const semicolonAmount = 7;

    // correct ip6.arpa form with ending removed will be 63 characters
    if (address.length !== 63) {
      throw new AddressError("Invalid 'ip6.arpa' form.");
    }

    const parts = address.split('.').reverse();

    for (let i = semicolonAmount; i > 0; i--) {
      const insertIndex = i * 4;
      parts.splice(insertIndex, 0, ':');
    }

    address = parts.join('');

    return new Address6(address);
  }

  /**
   * Return the Microsoft UNC transcription of the address
   * @memberof Address6
   * @instance
   * @returns {String} the Microsoft UNC transcription of the address
   */
  microsoftTranscription(): string {
    return `${this.correctForm().replace(/:/g, '-')}.ipv6-literal.net`;
  }

  /**
   * Return the first n bits of the address, defaulting to the subnet mask
   * @memberof Address6
   * @instance
   * @param {number} [mask=subnet] - the number of bits to mask
   * @returns {String} the first n bits of the address as a string
   */
  mask(mask: number = this.subnetMask): string {
    return this.getBitsBase2(0, mask);
  }

  /**
   * Return the number of possible subnets of a given size in the address
   * @memberof Address6
   * @instance
   * @param {number} [subnetSize=128] - the subnet size
   * @returns {String}
   */
  // TODO: probably useful to have a numeric version of this too
  possibleSubnets(subnetSize: number = 128): string {
    const availableBits = constants6.BITS - this.subnetMask;
    const subnetBits = Math.abs(subnetSize - constants6.BITS);
    const subnetPowers = availableBits - subnetBits;

    if (subnetPowers < 0) {
      return '0';
    }

    return addCommas((BigInt('2') ** BigInt(subnetPowers)).toString(10));
  }

  /**
   * Helper function getting start address.
   * @memberof Address6
   * @instance
   * @returns {bigint}
   */
  _startAddress(): bigint {
    return BigInt(`0b${this.mask() + '0'.repeat(constants6.BITS - this.subnetMask)}`);
  }

  /**
   * The first address in the range given by this address' subnet
   * Often referred to as the Network Address.
   * @memberof Address6
   * @instance
   * @returns {Address6}
   */
  startAddress(): Address6 {
    return Address6.fromBigInt(this._startAddress());
  }

  /**
   * The first host address in the range given by this address's subnet ie
   * the first address after the Network Address
   * @memberof Address6
   * @instance
   * @returns {Address6}
   */
  startAddressExclusive(): Address6 {
    const adjust = BigInt('1');
    return Address6.fromBigInt(this._startAddress() + adjust);
  }

  /**
   * Helper function getting end address.
   * @memberof Address6
   * @instance
   * @returns {bigint}
   */
  _endAddress(): bigint {
    return BigInt(`0b${this.mask() + '1'.repeat(constants6.BITS - this.subnetMask)}`);
  }

  /**
   * The last address in the range given by this address' subnet
   * Often referred to as the Broadcast
   * @memberof Address6
   * @instance
   * @returns {Address6}
   */
  endAddress(): Address6 {
    return Address6.fromBigInt(this._endAddress());
  }

  /**
   * The last host address in the range given by this address's subnet ie
   * the last address prior to the Broadcast Address
   * @memberof Address6
   * @instance
   * @returns {Address6}
   */
  endAddressExclusive(): Address6 {
    const adjust = BigInt('1');
    return Address6.fromBigInt(this._endAddress() - adjust);
  }

  /**
   * Return the scope of the address
   * @memberof Address6
   * @instance
   * @returns {String}
   */
  getScope(): string {
    let scope = constants6.SCOPES[parseInt(this.getBits(12, 16).toString(10), 10)];

    if (this.getType() === 'Global unicast' && scope !== 'Link local') {
      scope = 'Global';
    }

    return scope || 'Unknown';
  }

  /**
   * Return the type of the address
   * @memberof Address6
   * @instance
   * @returns {String}
   */
  getType(): string {
    for (const subnet of Object.keys(constants6.TYPES)) {
      if (this.isInSubnet(new Address6(subnet))) {
        return constants6.TYPES[subnet] as string;
      }
    }

    return 'Global unicast';
  }

  /**
   * Return the bits in the given range as a BigInt
   * @memberof Address6
   * @instance
   * @returns {bigint}
   */
  getBits(start: number, end: number): bigint {
    return BigInt(`0b${this.getBitsBase2(start, end)}`);
  }

  /**
   * Return the bits in the given range as a base-2 string
   * @memberof Address6
   * @instance
   * @returns {String}
   */
  getBitsBase2(start: number, end: number): string {
    return this.binaryZeroPad().slice(start, end);
  }

  /**
   * Return the bits in the given range as a base-16 string
   * @memberof Address6
   * @instance
   * @returns {String}
   */
  getBitsBase16(start: number, end: number): string {
    const length = end - start;

    if (length % 4 !== 0) {
      throw new Error('Length of bits to retrieve must be divisible by four');
    }

    return this.getBits(start, end)
      .toString(16)
      .padStart(length / 4, '0');
  }

  /**
   * Return the bits that are set past the subnet mask length
   * @memberof Address6
   * @instance
   * @returns {String}
   */
  getBitsPastSubnet(): string {
    return this.getBitsBase2(this.subnetMask, constants6.BITS);
  }

  /**
   * Return the reversed ip6.arpa form of the address
   * @memberof Address6
   * @param {Object} options
   * @param {boolean} options.omitSuffix - omit the "ip6.arpa" suffix
   * @instance
   * @returns {String}
   */
  reverseForm(options?: common.ReverseFormOptions): string {
    if (!options) {
      options = {};
    }

    const characters = Math.floor(this.subnetMask / 4);

    const reversed = this.canonicalForm()
      .replace(/:/g, '')
      .split('')
      .slice(0, characters)
      .reverse()
      .join('.');

    if (characters > 0) {
      if (options.omitSuffix) {
        return reversed;
      }

      return `${reversed}.ip6.arpa.`;
    }

    if (options.omitSuffix) {
      return '';
    }

    return 'ip6.arpa.';
  }

  /**
   * Return the correct form of the address
   * @memberof Address6
   * @instance
   * @returns {String}
   */
  correctForm(): string {
    let i;
    let groups = [];

    let zeroCounter = 0;
    const zeroes = [];

    for (i = 0; i < this.parsedAddress.length; i++) {
      const value = parseInt(this.parsedAddress[i], 16);

      if (value === 0) {
        zeroCounter++;
      }

      if (value !== 0 && zeroCounter > 0) {
        if (zeroCounter > 1) {
          zeroes.push([i - zeroCounter, i - 1]);
        }

        zeroCounter = 0;
      }
    }

    // Do we end with a string of zeroes?
    if (zeroCounter > 1) {
      zeroes.push([this.parsedAddress.length - zeroCounter, this.parsedAddress.length - 1]);
    }

    const zeroLengths = zeroes.map((n) => n[1] - n[0] + 1);

    if (zeroes.length > 0) {
      const index = zeroLengths.indexOf(Math.max(...zeroLengths) as number);

      groups = compact(this.parsedAddress, zeroes[index]);
    } else {
      groups = this.parsedAddress;
    }

    for (i = 0; i < groups.length; i++) {
      if (groups[i] !== 'compact') {
        groups[i] = parseInt(groups[i], 16).toString(16);
      }
    }

    let correct = groups.join(':');

    correct = correct.replace(/^compact$/, '::');
    correct = correct.replace(/(^compact)|(compact$)/, ':');
    correct = correct.replace(/compact/, '');

    return correct;
  }

  /**
   * Return a zero-padded base-2 string representation of the address
   * @memberof Address6
   * @instance
   * @returns {String}
   * @example
   * var address = new Address6('2001:4860:4001:803::1011');
   * address.binaryZeroPad();
   * // '0010000000000001010010000110000001000000000000010000100000000011
   * //  0000000000000000000000000000000000000000000000000001000000010001'
   */
  binaryZeroPad(): string {
    return this.bigInt().toString(2).padStart(constants6.BITS, '0');
  }

  // TODO: Improve the semantics of this helper function
  parse4in6(address: string): string {
    const groups = address.split(':');
    const lastGroup = groups.slice(-1)[0];

    const address4 = lastGroup.match(constants4.RE_ADDRESS);

    if (address4) {
      this.parsedAddress4 = address4[0];
      this.address4 = new Address4(this.parsedAddress4);

      for (let i = 0; i < this.address4.groups; i++) {
        if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) {
          throw new AddressError(
            "IPv4 addresses can't have leading zeroes.",
            address.replace(
              constants4.RE_ADDRESS,
              this.address4.parsedAddress.map(spanLeadingZeroes4).join('.'),
            ),
          );
        }
      }

      this.v4 = true;

      groups[groups.length - 1] = this.address4.toGroup6();

      address = groups.join(':');
    }

    return address;
  }

  // TODO: Make private?
  parse(address: string): string[] {
    address = this.parse4in6(address);

    const badCharacters = address.match(constants6.RE_BAD_CHARACTERS);

    if (badCharacters) {
      throw new AddressError(
        `Bad character${
          badCharacters.length > 1 ? 's' : ''
        } detected in address: ${badCharacters.join('')}`,
        address.replace(constants6.RE_BAD_CHARACTERS, '<span class="parse-error">$1</span>'),
      );
    }

    const badAddress = address.match(constants6.RE_BAD_ADDRESS);

    if (badAddress) {
      throw new AddressError(
        `Address failed regex: ${badAddress.join('')}`,
        address.replace(constants6.RE_BAD_ADDRESS, '<span class="parse-error">$1</span>'),
      );
    }

    let groups: string[] = [];

    const halves = address.split('::');

    if (halves.length === 2) {
      let first = halves[0].split(':');
      let last = halves[1].split(':');

      if (first.length === 1 && first[0] === '') {
        first = [];
      }

      if (last.length === 1 && last[0] === '') {
        last = [];
      }

      const remaining = this.groups - (first.length + last.length);

      if (!remaining) {
        throw new AddressError('Error parsing groups');
      }

      this.elidedGroups = remaining;

      this.elisionBegin = first.length;
      this.elisionEnd = first.length + this.elidedGroups;

      groups = groups.concat(first);

      for (let i = 0; i < remaining; i++) {
        groups.push('0');
      }

      groups = groups.concat(last);
    } else if (halves.length === 1) {
      groups = address.split(':');

      this.elidedGroups = 0;
    } else {
      throw new AddressError('Too many :: groups found');
    }

    groups = groups.map((group: string) => parseInt(group, 16).toString(16));

    if (groups.length !== this.groups) {
      throw new AddressError('Incorrect number of groups found');
    }

    return groups;
  }

  /**
   * Return the canonical form of the address
   * @memberof Address6
   * @instance
   * @returns {String}
   */
  canonicalForm(): string {
    return this.parsedAddress.map(paddedHex).join(':');
  }

  /**
   * Return the decimal form of the address
   * @memberof Address6
   * @instance
   * @returns {String}
   */
  decimal(): string {
    return this.parsedAddress.map((n) => parseInt(n, 16).toString(10).padStart(5, '0')).join(':');
  }

  /**
   * Return the address as a BigInt
   * @memberof Address6
   * @instance
   * @returns {bigint}
   */
  bigInt(): bigint {
    return BigInt(`0x${this.parsedAddress.map(paddedHex).join('')}`);
  }

  /**
   * Return the last two groups of this address as an IPv4 address string
   * @memberof Address6
   * @instance
   * @returns {Address4}
   * @example
   * var address = new Address6('2001:4860:4001::1825:bf11');
   * address.to4().correctForm(); // '24.37.191.17'
   */
  to4(): Address4 {
    const binary = this.binaryZeroPad().split('');

    return Address4.fromHex(BigInt(`0b${binary.slice(96, 128).join('')}`).toString(16));
  }

  /**
   * Return the v4-in-v6 form of the address
   * @memberof Address6
   * @instance
   * @returns {String}
   */
  to4in6(): string {
    const address4 = this.to4();
    const address6 = new Address6(this.parsedAddress.slice(0, 6).join(':'), 6);

    const correct = address6.correctForm();

    let infix = '';

    if (!/:$/.test(correct)) {
      infix = ':';
    }

    return correct + infix + address4.address;
  }

  /**
   * Return an object containing the Teredo properties of the address
   * @memberof Address6
   * @instance
   * @returns {Object}
   */
  inspectTeredo(): TeredoProperties {
    /*
    - Bits 0 to 31 are set to the Teredo prefix (normally 2001:0000::/32).
    - Bits 32 to 63 embed the primary IPv4 address of the Teredo server that
      is used.
    - Bits 64 to 79 can be used to define some flags. Currently only the
      higher order bit is used; it is set to 1 if the Teredo client is
      located behind a cone NAT, 0 otherwise. For Microsoft's Windows Vista
      and Windows Server 2008 implementations, more bits are used. In those
      implementations, the format for these 16 bits is "CRAAAAUG AAAAAAAA",
      where "C" remains the "Cone" flag. The "R" bit is reserved for future
      use. The "U" bit is for the Universal/Local flag (set to 0). The "G" bit
      is Individual/Group flag (set to 0). The A bits are set to a 12-bit
      randomly generated number chosen by the Teredo client to introduce
      additional protection for the Teredo node against IPv6-based scanning
      attacks.
    - Bits 80 to 95 contains the obfuscated UDP port number. This is the
      port number that is mapped by the NAT to the Teredo client with all
      bits inverted.
    - Bits 96 to 127 contains the obfuscated IPv4 address. This is the
      public IPv4 address of the NAT with all bits inverted.
    */
    const prefix = this.getBitsBase16(0, 32);

    const bitsForUdpPort: bigint = this.getBits(80, 96);
    // eslint-disable-next-line no-bitwise
    const udpPort = (bitsForUdpPort ^ BigInt('0xffff')).toString();

    const server4 = Address4.fromHex(this.getBitsBase16(32, 64));

    const bitsForClient4 = this.getBits(96, 128);
    // eslint-disable-next-line no-bitwise
    const client4 = Address4.fromHex((bitsForClient4 ^ BigInt('0xffffffff')).toString(16));

    const flagsBase2 = this.getBitsBase2(64, 80);

    const coneNat = testBit(flagsBase2, 15);
    const reserved = testBit(flagsBase2, 14);
    const groupIndividual = testBit(flagsBase2, 8);
    const universalLocal = testBit(flagsBase2, 9);
    const nonce = BigInt(`0b${flagsBase2.slice(2, 6) + flagsBase2.slice(8, 16)}`).toString(10);

    return {
      prefix: `${prefix.slice(0, 4)}:${prefix.slice(4, 8)}`,
      server4: server4.address,
      client4: client4.address,
      flags: flagsBase2,
      coneNat,
      microsoft: {
        reserved,
        universalLocal,
        groupIndividual,
        nonce,
      },
      udpPort,
    };
  }

  /**
   * Return an object containing the 6to4 properties of the address
   * @memberof Address6
   * @instance
   * @returns {Object}
   */
  inspect6to4(): SixToFourProperties {
    /*
    - Bits 0 to 15 are set to the 6to4 prefix (2002::/16).
    - Bits 16 to 48 embed the IPv4 address of the 6to4 gateway that is used.
    */

    const prefix = this.getBitsBase16(0, 16);

    const gateway = Address4.fromHex(this.getBitsBase16(16, 48));

    return {
      prefix: prefix.slice(0, 4),
      gateway: gateway.address,
    };
  }

  /**
   * Return a v6 6to4 address from a v6 v4inv6 address
   * @memberof Address6
   * @instance
   * @returns {Address6}
   */
  to6to4(): Address6 | null {
    if (!this.is4()) {
      return null;
    }

    const addr6to4 = [
      '2002',
      this.getBitsBase16(96, 112),
      this.getBitsBase16(112, 128),
      '',
      '/16',
    ].join(':');

    return new Address6(addr6to4);
  }

  /**
   * Return a byte array
   * @memberof Address6
   * @instance
   * @returns {Array}
   */
  toByteArray(): number[] {
    const valueWithoutPadding = this.bigInt().toString(16);
    const leadingPad = '0'.repeat(valueWithoutPadding.length % 2);

    const value = `${leadingPad}${valueWithoutPadding}`;

    const bytes = [];
    for (let i = 0, length = value.length; i < length; i += 2) {
      bytes.push(parseInt(value.substring(i, i + 2), 16));
    }

    return bytes;
  }

  /**
   * Return an unsigned byte array
   * @memberof Address6
   * @instance
   * @returns {Array}
   */
  toUnsignedByteArray(): number[] {
    return this.toByteArray().map(unsignByte);
  }

  /**
   * Convert a byte array to an Address6 object
   * @memberof Address6
   * @static
   * @returns {Address6}
   */
  static fromByteArray(bytes: Array<any>): Address6 {
    return this.fromUnsignedByteArray(bytes.map(unsignByte));
  }

  /**
   * Convert an unsigned byte array to an Address6 object
   * @memberof Address6
   * @static
   * @returns {Address6}
   */
  static fromUnsignedByteArray(bytes: Array<any>): Address6 {
    const BYTE_MAX = BigInt('256');
    let result = BigInt('0');
    let multiplier = BigInt('1');

    for (let i = bytes.length - 1; i >= 0; i--) {
      result += multiplier * BigInt(bytes[i].toString(10));

      multiplier *= BYTE_MAX;
    }

    return Address6.fromBigInt(result);
  }

  // #region Attributes
  /**
   * Returns true if the given address is in the subnet of the current address
   * @memberof Address6
   * @instance
   * @returns {boolean}
   */
  isInSubnet = common.isInSubnet;

  /**
   * Returns true if the address is correct, false otherwise
   * @memberof Address6
   * @instance
   * @returns {boolean}
   */
  isCorrect = common.isCorrect(constants6.BITS);

  /**
   * Returns true if the address is in the canonical form, false otherwise
   * @memberof Address6
   * @instance
   * @returns {boolean}
   */
  isCanonical(): boolean {
    return this.addressMinusSuffix === this.canonicalForm();
  }

  /**
   * Returns true if the address is a link local address, false otherwise
   * @memberof Address6
   * @instance
   * @returns {boolean}
   */
  isLinkLocal(): boolean {
    // Zeroes are required, i.e. we can't check isInSubnet with 'fe80::/10'
    if (
      this.getBitsBase2(0, 64) ===
      '1111111010000000000000000000000000000000000000000000000000000000'
    ) {
      return true;
    }

    return false;
  }

  /**
   * Returns true if the address is a multicast address, false otherwise
   * @memberof Address6
   * @instance
   * @returns {boolean}
   */
  isMulticast(): boolean {
    return this.getType() === 'Multicast';
  }

  /**
   * Returns true if the address is a v4-in-v6 address, false otherwise
   * @memberof Address6
   * @instance
   * @returns {boolean}
   */
  is4(): boolean {
    return this.v4;
  }

  /**
   * Returns true if the address is a Teredo address, false otherwise
   * @memberof Address6
   * @instance
   * @returns {boolean}
   */
  isTeredo(): boolean {
    return this.isInSubnet(new Address6('2001::/32'));
  }

  /**
   * Returns true if the address is a 6to4 address, false otherwise
   * @memberof Address6
   * @instance
   * @returns {boolean}
   */
  is6to4(): boolean {
    return this.isInSubnet(new Address6('2002::/16'));
  }

  /**
   * Returns true if the address is a loopback address, false otherwise
   * @memberof Address6
   * @instance
   * @returns {boolean}
   */
  isLoopback(): boolean {
    return this.getType() === 'Loopback';
  }
  // #endregion

  // #region HTML
  /**
   * @returns {String} the address in link form with a default port of 80
   */
  href(optionalPort?: number | string): string {
    if (optionalPort === undefined) {
      optionalPort = '';
    } else {
      optionalPort = `:${optionalPort}`;
    }

    return `http://[${this.correctForm()}]${optionalPort}/`;
  }

  /**
   * @returns {String} a link suitable for conveying the address via a URL hash
   */
  link(options?: { className?: string; prefix?: string; v4?: boolean }): string {
    if (!options) {
      options = {};
    }

    if (options.className === undefined) {
      options.className = '';
    }

    if (options.prefix === undefined) {
      options.prefix = '/#address=';
    }

    if (options.v4 === undefined) {
      options.v4 = false;
    }

    let formFunction = this.correctForm;

    if (options.v4) {
      formFunction = this.to4in6;
    }

    const form = formFunction.call(this);

    if (options.className) {
      return `<a href="${options.prefix}${form}" class="${options.className}">${form}</a>`;
    }

    return `<a href="${options.prefix}${form}">${form}</a>`;
  }

  /**
   * Groups an address
   * @returns {String}
   */
  group(): string {
    if (this.elidedGroups === 0) {
      // The simple case
      return helpers.simpleGroup(this.address).join(':');
    }

    assert(typeof this.elidedGroups === 'number');
    assert(typeof this.elisionBegin === 'number');

    // The elided case
    const output = [];

    const [left, right] = this.address.split('::');

    if (left.length) {
      output.push(...helpers.simpleGroup(left));
    } else {
      output.push('');
    }

    const classes = ['hover-group'];

    for (let i = this.elisionBegin; i < this.elisionBegin + this.elidedGroups; i++) {
      classes.push(`group-${i}`);
    }

    output.push(`<span class="${classes.join(' ')}"></span>`);

    if (right.length) {
      output.push(...helpers.simpleGroup(right, this.elisionEnd));
    } else {
      output.push('');
    }

    if (this.is4()) {
      assert(this.address4 instanceof Address4);

      output.pop();
      output.push(this.address4.groupForV6());
    }

    return output.join(':');
  }
  // #endregion

  // #region Regular expressions
  /**
   * Generate a regular expression string that can be used to find or validate
   * all variations of this address
   * @memberof Address6
   * @instance
   * @param {boolean} substringSearch
   * @returns {string}
   */
  regularExpressionString(this: Address6, substringSearch: boolean = false): string {
    let output: string[] = [];

    // TODO: revisit why this is necessary
    const address6 = new Address6(this.correctForm());

    if (address6.elidedGroups === 0) {
      // The simple case
      output.push(simpleRegularExpression(address6.parsedAddress));
    } else if (address6.elidedGroups === constants6.GROUPS) {
      // A completely elided address
      output.push(possibleElisions(constants6.GROUPS));
    } else {
      // A partially elided address
      const halves = address6.address.split('::');

      if (halves[0].length) {
        output.push(simpleRegularExpression(halves[0].split(':')));
      }

      assert(typeof address6.elidedGroups === 'number');

      output.push(
        possibleElisions(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0),
      );

      if (halves[1].length) {
        output.push(simpleRegularExpression(halves[1].split(':')));
      }

      output = [output.join(':')];
    }

    if (!substringSearch) {
      output = [
        '(?=^|',
        ADDRESS_BOUNDARY,
        '|[^\\w\\:])(',
        ...output,
        ')(?=[^\\w\\:]|',
        ADDRESS_BOUNDARY,
        '|$)',
      ];
    }

    return output.join('');
  }

  /**
   * Generate a regular expression that can be used to find or validate all
   * variations of this address.
   * @memberof Address6
   * @instance
   * @param {boolean} substringSearch
   * @returns {RegExp}
   */
  regularExpression(this: Address6, substringSearch: boolean = false): RegExp {
    return new RegExp(this.regularExpressionString(substringSearch), 'i');
  }
  // #endregion
}
