// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:meta/meta.dart';
import 'constants.dart';
import 'packet.dart';

/// Enumeration of support resource record types.
abstract class ResourceRecordType {
  // This class is intended to be used as a namespace, and should not be
  // extended directly.
  ResourceRecordType._();

  /// An IPv4 Address record, also known as an "A" record. It has a value of 1.
  static const int addressIPv4 = 1;

  /// An IPv6 Address record, also known as an "AAAA" record.  It has a vaule of
  /// 28.
  static const int addressIPv6 = 28;

  /// An IP Address reverse map record, also known as a "PTR" recored. It has a
  /// value of 12.
  static const int serverPointer = 12;

  /// An available service record, also known as an "SRV" record.  It has a
  /// value of 33.
  static const int service = 33;

  /// A text record, also known as a "TXT" record.  It has a value of 16.
  static const int text = 16;

  // TODO(dnfield): Support ANY in some meaningful way.  Might be server only.
  // /// A query for all records of all types known to the name server.
  // static const int any = 255;

  /// Checks that a given int is a valid ResourceRecordType.
  ///
  /// This method is intended to be called only from an `assert()`.
  static bool debugAssertValid(int resourceRecordType) {
    return resourceRecordType == addressIPv4 ||
        resourceRecordType == addressIPv6 ||
        resourceRecordType == serverPointer ||
        resourceRecordType == service ||
        resourceRecordType == text;
  }

  /// Prints a debug-friendly version of the resource record type value.
  static String toDebugString(int resourceRecordType) {
    switch (resourceRecordType) {
      case addressIPv4:
        return 'A (IPv4 Address)';
      case addressIPv6:
        return 'AAAA (IPv6 Address)';
      case serverPointer:
        return 'PTR (Domain Name Pointer)';
      case service:
        return 'SRV (Service record)';
      case text:
        return 'TXT (Text)';
    }
    return 'Unknown ($resourceRecordType)';
  }
}

/// Represents a DNS query.
@immutable
class ResourceRecordQuery {
  /// Creates a new ResourceRecordQuery.
  ///
  /// Most callers should prefer one of the named constructors.
  ResourceRecordQuery(
    this.resourceRecordType,
    this.fullyQualifiedName,
    this.questionType,
  ) : assert(ResourceRecordType.debugAssertValid(resourceRecordType));

  /// An A (IPv4) query.
  ResourceRecordQuery.addressIPv4(
    String name, {
    bool isMulticast = true,
  }) : this(
          ResourceRecordType.addressIPv4,
          name,
          isMulticast ? QuestionType.multicast : QuestionType.unicast,
        );

  /// An AAAA (IPv6) query.
  ResourceRecordQuery.addressIPv6(
    String name, {
    bool isMulticast = true,
  }) : this(
          ResourceRecordType.addressIPv6,
          name,
          isMulticast ? QuestionType.multicast : QuestionType.unicast,
        );

  /// A PTR (Server pointer) query.
  ResourceRecordQuery.serverPointer(
    String name, {
    bool isMulticast = true,
  }) : this(
          ResourceRecordType.serverPointer,
          name,
          isMulticast ? QuestionType.multicast : QuestionType.unicast,
        );

  /// An SRV (Service) query.
  ResourceRecordQuery.service(
    String name, {
    bool isMulticast = true,
  }) : this(
          ResourceRecordType.service,
          name,
          isMulticast ? QuestionType.multicast : QuestionType.unicast,
        );

  /// A TXT (Text record) query.
  ResourceRecordQuery.text(
    String name, {
    bool isMulticast = true,
  }) : this(
          ResourceRecordType.text,
          name,
          isMulticast ? QuestionType.multicast : QuestionType.unicast,
        );

  /// Tye type of resource record - one of [ResourceRecordType]'s values.
  final int resourceRecordType;

  /// The Fully Qualified Domain Name associated with the request.
  final String fullyQualifiedName;

  /// The [QuestionType], i.e. multicast or unicast.
  final int questionType;

  /// Convenience accessor to determine whether the question type is multicast.
  bool get isMulticast => questionType == QuestionType.multicast;

  /// Convenience accessor to determine whether the question type is unicast.
  bool get isUnicast => questionType == QuestionType.unicast;

  /// Encodes this query to the raw wire format.
  List<int> encode() {
    return encodeMDnsQuery(
      fullyQualifiedName,
      type: resourceRecordType,
      multicast: isMulticast,
    );
  }

  @override
  int get hashCode =>
      Object.hash(resourceRecordType, fullyQualifiedName, questionType);

  @override
  bool operator ==(Object other) {
    return other is ResourceRecordQuery &&
        other.resourceRecordType == resourceRecordType &&
        other.fullyQualifiedName == fullyQualifiedName &&
        other.questionType == questionType;
  }

  @override
  String toString() =>
      'ResourceRecordQuery{$fullyQualifiedName, type: ${ResourceRecordType.toDebugString(resourceRecordType)}, isMulticast: $isMulticast}';
}

/// Base implementation of DNS resource records (RRs).
@immutable
abstract class ResourceRecord {
  /// Creates a new ResourceRecord.
  const ResourceRecord(this.resourceRecordType, this.name, this.validUntil);

  /// The FQDN for this record.
  final String name;

  /// The epoch time at which point this record is valid for in the cache.
  final int validUntil;

  /// The raw resource record value.  See [ResourceRecordType] for supported values.
  final int resourceRecordType;

  String get _additionalInfo;

  @override
  String toString() =>
      '$runtimeType{$name, validUntil: ${DateTime.fromMillisecondsSinceEpoch(validUntil)}, $_additionalInfo}';

  @override
  int get hashCode => Object.hash(name, validUntil, resourceRecordType);

  @override
  bool operator ==(Object other) {
    return other is ResourceRecord &&
        other.name == name &&
        other.validUntil == validUntil &&
        other.resourceRecordType == resourceRecordType;
  }

  /// Low level method for encoding this record into an mDNS packet.
  ///
  /// Subclasses should provide the packet format of their encapsulated data
  /// into a `Uint8List`, which could then be used to write a pakcet to send
  /// as a response for this record type.
  Uint8List encodeResponseRecord();
}

/// A Service Pointer for reverse mapping an IP address (DNS "PTR").
class PtrResourceRecord extends ResourceRecord {
  /// Creates a new PtrResourceRecord.
  const PtrResourceRecord(
    String name,
    int validUntil, {
    required this.domainName,
  }) : super(ResourceRecordType.serverPointer, name, validUntil);

  /// The FQDN for this record.
  final String domainName;

  @override
  String get _additionalInfo => 'domainName: $domainName';

  @override
  int get hashCode => Object.hash(domainName.hashCode, super.hashCode);

  @override
  bool operator ==(Object other) {
    return super == other &&
        other is PtrResourceRecord &&
        other.domainName == domainName;
  }

  @override
  Uint8List encodeResponseRecord() {
    return Uint8List.fromList(utf8.encode(domainName));
  }
}

/// An IP Address record for IPv4 (DNS "A") or IPv6 (DNS "AAAA") records.
class IPAddressResourceRecord extends ResourceRecord {
  /// Creates a new IPAddressResourceRecord.
  IPAddressResourceRecord(
    String name,
    int validUntil, {
    required this.address,
  }) : super(
            address.type == InternetAddressType.IPv4
                ? ResourceRecordType.addressIPv4
                : ResourceRecordType.addressIPv6,
            name,
            validUntil);

  /// The [InternetAddress] for this record.
  final InternetAddress address;

  @override
  String get _additionalInfo => 'address: $address';

  @override
  int get hashCode => Object.hash(address.hashCode, super.hashCode);

  @override
  bool operator ==(Object other) {
    return super == other &&
        other is IPAddressResourceRecord &&
        other.address == address;
  }

  @override
  Uint8List encodeResponseRecord() {
    return Uint8List.fromList(address.rawAddress);
  }
}

/// A Service record, capturing a host target and port (DNS "SRV").
class SrvResourceRecord extends ResourceRecord {
  /// Creates a new service record.
  const SrvResourceRecord(
    String name,
    int validUntil, {
    required this.target,
    required this.port,
    required this.priority,
    required this.weight,
  }) : super(ResourceRecordType.service, name, validUntil);

  /// The hostname for this record.
  final String target;

  /// The port for this record.
  final int port;

  /// The relative priority of this service.
  final int priority;

  /// The weight (used when multiple services have the same priority).
  final int weight;

  @override
  String get _additionalInfo =>
      'target: $target, port: $port, priority: $priority, weight: $weight';

  @override
  int get hashCode =>
      Object.hash(target, port, priority, weight, super.hashCode);

  @override
  bool operator ==(Object other) {
    return super == other &&
        other is SrvResourceRecord &&
        other.target == target &&
        other.port == port &&
        other.priority == priority &&
        other.weight == weight;
  }

  @override
  Uint8List encodeResponseRecord() {
    final List<int> data = utf8.encode(target);
    final Uint8List result = Uint8List(data.length + 7);
    final ByteData resultData = ByteData.view(result.buffer);
    resultData.setUint16(0, priority);
    resultData.setUint16(2, weight);
    resultData.setUint16(4, port);
    result[6] = data.length;
    return result..setRange(7, data.length, data);
  }
}

/// A Text record, contianing additional textual data (DNS "TXT").
class TxtResourceRecord extends ResourceRecord {
  /// Creates a new text record.
  const TxtResourceRecord(
    String name,
    int validUntil, {
    required this.text,
  }) : super(ResourceRecordType.text, name, validUntil);

  /// The raw text from this record.
  final String text;

  @override
  String get _additionalInfo => 'text: $text';

  @override
  int get hashCode => Object.hash(text.hashCode, super.hashCode);

  @override
  bool operator ==(Object other) =>
      super == other && other is TxtResourceRecord && other.text == text;

  @override
  Uint8List encodeResponseRecord() {
    return Uint8List.fromList(utf8.encode(text));
  }
}
