// 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 'dart:io';

/// A class that delegates header access and setting to many [HttpHeaders]
/// instances.
class MultiHeaders implements HttpHeaders {
  /// The wrapped headers.
  final Set<HttpHeaders> _headers;

  @override
  bool get chunkedTransferEncoding => _headers.first.chunkedTransferEncoding;
  @override
  set chunkedTransferEncoding(bool value) {
    for (var headers in _headers) {
      headers.chunkedTransferEncoding = value;
    }
  }

  @override
  int get contentLength => _headers.first.contentLength;
  @override
  set contentLength(int value) {
    for (var headers in _headers) {
      headers.contentLength = value;
    }
  }

  @override
  ContentType? get contentType => _headers.first.contentType;
  @override
  set contentType(ContentType? value) {
    for (var headers in _headers) {
      headers.contentType = value;
    }
  }

  @override
  DateTime? get date => _headers.first.date;
  @override
  set date(DateTime? value) {
    for (var headers in _headers) {
      headers.date = value;
    }
  }

  @override
  DateTime? get expires => _headers.first.expires;
  @override
  set expires(DateTime? value) {
    for (var headers in _headers) {
      headers.expires = value;
    }
  }

  @override
  String? get host => _headers.first.host;
  @override
  set host(String? value) {
    for (var headers in _headers) {
      headers.host = value;
    }
  }

  @override
  DateTime? get ifModifiedSince => _headers.first.ifModifiedSince;
  @override
  set ifModifiedSince(DateTime? value) {
    for (var headers in _headers) {
      headers.ifModifiedSince = value;
    }
  }

  @override
  bool get persistentConnection => _headers.first.persistentConnection;
  @override
  set persistentConnection(bool value) {
    for (var headers in _headers) {
      headers.persistentConnection = value;
    }
  }

  @override
  int? get port => _headers.first.port;
  @override
  set port(int? value) {
    for (var headers in _headers) {
      headers.port = value;
    }
  }

  MultiHeaders(Iterable<HttpHeaders> headers) : _headers = headers.toSet();

  @override
  void add(String name, Object value, {bool preserveHeaderCase = false}) {
    for (var headers in _headers) {
      headers.add(name, value);
    }
  }

  @override
  void forEach(void Function(String name, List<String> values) f) =>
      _headers.first.forEach(f);

  @override
  void noFolding(String name) {
    for (var headers in _headers) {
      headers.noFolding(name);
    }
  }

  @override
  void remove(String name, Object value) {
    for (var headers in _headers) {
      headers.remove(name, value);
    }
  }

  @override
  void removeAll(String name) {
    for (var headers in _headers) {
      headers.removeAll(name);
    }
  }

  @override
  void set(String name, Object value, {bool preserveHeaderCase = false}) {
    for (var headers in _headers) {
      headers.set(name, value);
    }
  }

  @override
  String? value(String name) => _headers.first.value(name);

  @override
  List<String>? operator [](String name) => _headers.first[name];

  @override
  void clear() {
    for (var headers in _headers) {
      headers.clear();
    }
  }
}
