// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.core.http;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Stream;

/**
 * A collection of headers on an HTTP request or response.
 */
public class HttpHeaders implements Iterable<HttpHeader> {
    private final Map<String, HttpHeader> headers = new HashMap<>();

    /**
     * Create an empty HttpHeaders instance.
     */
    public HttpHeaders() {
    }

    /**
     * Create a HttpHeaders instance with the provided initial headers.
     *
     * @param headers the map of initial headers
     */
    public HttpHeaders(Map<String, String> headers) {
        for (final Map.Entry<String, String> header : headers.entrySet()) {
            this.put(header.getKey(), header.getValue());
        }
    }

    /**
     * Create a HttpHeaders instance with the provided initial headers.
     *
     * @param headers the collection of initial headers
     */
    public HttpHeaders(Iterable<HttpHeader> headers) {
        this();

        for (final HttpHeader header : headers) {
            this.put(header.getName(), header.getValue());
        }
    }

    /**
     * Gets the number of headers in the collection.
     *
     * @return the number of headers in this collection.
     */
    public int getSize() {
        return headers.size();
    }

    /**
     * Set a header.
     *
     * If header with same name already exists then the value will be overwritten.
     *
     * @param name the name
     * @param value the value
     * @return The updated HttpHeaders object
     */
    public HttpHeaders put(String name, String value) {
        headers.put(formatKey(name), new HttpHeader(name, value));
        return this;
    }

    /**
     * Get the {@link HttpHeader header} for the provided header name. Null will be returned if the header isn't found.
     *
     * @param name the name of the header to find.
     * @return the header if found, null otherwise.
     */
    public HttpHeader get(String name) {
        return headers.get(formatKey(name));
    }

    /**
     * Get the header value for the provided header name. Null will be returned if the header
     * name isn't found.
     *
     * @param name the name of the header to look for
     * @return The String value of the header, or null if the header isn't found
     */
    public String getValue(String name) {
        final HttpHeader header = get(name);
        return header == null ? null : header.getValue();
    }

    /**
     * Get the header values for the provided header name. Null will be returned if
     * the header name isn't found.
     *
     * @param name the name of the header to look for
     * @return the values of the header, or null if the header isn't found
     */
    public String[] getValues(String name) {
        final HttpHeader header = get(name);
        return header == null ? null : header.getValues();
    }

    private String formatKey(final String key) {
        return key.toLowerCase(Locale.ROOT);
    }

    /**
     * Get {@link Map} representation of the HttpHeaders collection.
     *
     * @return the headers as map
     */
    public Map<String, String> toMap() {
        final Map<String, String> result = new HashMap<>();
        for (final HttpHeader header : headers.values()) {
            result.put(header.getName(), header.getValue());
        }
        return result;
    }

    @Override
    public Iterator<HttpHeader> iterator() {
        return headers.values().iterator();
    }

    /**
     * Get a {@link Stream} representation of the HttpHeader values in this instance.
     *
     * @return A {@link Stream} of all header values in this instance.
     */
    public Stream<HttpHeader> stream() {
        return headers.values().stream();
    }
}

@@ -216,24 +216,71 @@
 a.util.Map;%0A
+import java.util.concurrent.ConcurrentHashMap;%0A
 import java.
@@ -478,24 +478,34 @@
 aders = new 
+Concurrent
 HashMap%3C%3E();
@@ -1519,17 +1519,67 @@
  Set
+s
  a 
-header
+%7B@link HttpHeader header%7D with the given name and value
 .%0A  
@@ -1590,16 +1590,19 @@
 %0A     * 
+%3Cp%3E
 If heade
@@ -1668,16 +1668,20 @@
 written.
+%3C/p%3E
 %0A     *%0A
@@ -1957,24 +1957,25 @@
 *%0A     * Get
+s
  the %7B@link 
@@ -2019,36 +2019,39 @@
 eader name. 
-Null will be
+%7B@code Null%7D is
  returned if
@@ -2063,24 +2063,31 @@
 header isn't
+%0A     *
  found.%0A    
@@ -2312,32 +2312,50 @@
   * 
-Get the header value for
+Removes the %7B@link HttpHeader header%7D with
  the
@@ -2373,36 +2373,39 @@
 eader name. 
-Null will be
+%7B@code Null%7D is
  returned if
@@ -2422,21 +2422,16 @@
 r%0A     *
- name
  isn't f
@@ -2492,42 +2492,392 @@
  to 
-look for%0A     * @return The String
+remove.%0A     * @return the header if removed, null otherwise.%0A     */%0A    public HttpHeader remove(String name) %7B%0A        return headers.remove(formatKey(name));%0A    %7D%0A%0A    /**%0A     * Get the value for the provided header name. %7B@code Null%7D is returned if the header name isn't found.%0A     *%0A     * @param name the name of the header whose value is being retrieved.%0A     * @return the
  val
@@ -3111,23 +3111,16 @@
 Get the 
-header 
 values f
@@ -3152,20 +3152,23 @@
 me. 
-Null will be
+%7B@code Null%7D is
  ret
@@ -3175,23 +3175,16 @@
 urned if
-%0A     *
  the hea
@@ -3204,32 +3204,125 @@
 t found.%0A     *%0A
+     * %3Cp%3EThis returns %7B@link #getValue(String) getValue%7D split by %7B@code comma%7D.%3C/p%3E%0A     *%0A
      * @param na
@@ -3351,19 +3351,39 @@
 der 
-to look for
+whose value is being retrieved.
 %0A   
@@ -3737,16 +3737,19 @@
    * Get
+s a
  %7B@link 

Add remove to HttpHeaders (#5704)