// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:collection/collection.dart';
import 'package:string_scanner/string_scanner.dart';

import 'case_insensitive_map.dart';
import 'scan.dart';
import 'utils.dart';

/// A regular expression matching a character that needs to be backslash-escaped
/// in a quoted string.
final _escapedChar = RegExp(r'["\x00-\x1F\x7F]');

/// A class representing an HTTP media type, as used in Accept and Content-Type
/// headers.
///
/// This is immutable; new instances can be created based on an old instance by
/// calling [change].
class MediaType {
  /// The primary identifier of the MIME type.
  ///
  /// This is always lowercase.
  final String type;

  /// The secondary identifier of the MIME type.
  ///
  /// This is always lowercase.
  final String subtype;

  /// The parameters to the media type.
  ///
  /// This map is immutable and the keys are case-insensitive.
  final Map<String, String> parameters;

  /// The media type's MIME type.
  String get mimeType => '$type/$subtype';

  /// Parses a media type.
  ///
  /// This will throw a FormatError if the media type is invalid.
  factory MediaType.parse(String mediaType) =>
      // This parsing is based on sections 3.6 and 3.7 of the HTTP spec:
      // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html.
      wrapFormatException('media type', mediaType, () {
        final scanner = StringScanner(mediaType);
        scanner.scan(whitespace);
        scanner.expect(token);
        final type = scanner.lastMatch![0]!;
        scanner.expect('/');
        scanner.expect(token);
        final subtype = scanner.lastMatch![0]!;
        scanner.scan(whitespace);

        final parameters = <String, String>{};
        while (scanner.scan(';')) {
          scanner.scan(whitespace);
          scanner.expect(token);
          final attribute = scanner.lastMatch![0]!;
          scanner.expect('=');

          String value;
          if (scanner.scan(token)) {
            value = scanner.lastMatch![0]!;
          } else {
            value = expectQuotedString(scanner);
          }

          scanner.scan(whitespace);
          parameters[attribute] = value;
        }

        scanner.expectDone();
        return MediaType(type, subtype, parameters);
      });

  MediaType(String type, String subtype, [Map<String, String>? parameters])
      : type = type.toLowerCase(),
        subtype = subtype.toLowerCase(),
        parameters = UnmodifiableMapView(
            parameters == null ? {} : CaseInsensitiveMap.from(parameters));

  /// Returns a copy of this [MediaType] with some fields altered.
  ///
  /// [type] and [subtype] alter the corresponding fields. [mimeType] is parsed
  /// and alters both the [type] and [subtype] fields; it cannot be passed along
  /// with [type] or [subtype].
  ///
  /// [parameters] overwrites and adds to the corresponding field. If
  /// [clearParameters] is passed, it replaces the corresponding field entirely
  /// instead.
  MediaType change(
      {String? type,
      String? subtype,
      String? mimeType,
      Map<String, String>? parameters,
      bool clearParameters = false}) {
    if (mimeType != null) {
      if (type != null) {
        throw ArgumentError('You may not pass both [type] and [mimeType].');
      } else if (subtype != null) {
        throw ArgumentError('You may not pass both [subtype] and '
            '[mimeType].');
      }

      final segments = mimeType.split('/');
      if (segments.length != 2) {
        throw FormatException('Invalid mime type "$mimeType".');
      }

      type = segments[0];
      subtype = segments[1];
    }

    type ??= this.type;
    subtype ??= this.subtype;
    parameters ??= {};

    if (!clearParameters) {
      final newParameters = parameters;
      parameters = Map.from(this.parameters);
      parameters.addAll(newParameters);
    }

    return MediaType(type, subtype, parameters);
  }

  /// Converts the media type to a string.
  ///
  /// This will produce a valid HTTP media type.
  @override
  String toString() {
    final buffer = StringBuffer()..write(type)..write('/')..write(subtype);

    parameters.forEach((attribute, value) {
      buffer.write('; $attribute=');
      if (nonToken.hasMatch(value)) {
        buffer
          ..write('"')
          ..write(
              value.replaceAllMapped(_escapedChar, (match) => '\\${match[0]}'))
          ..write('"');
      } else {
        buffer.write(value);
      }
    });

    return buffer.toString();
  }
}
