// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau.http.header;

import static org.apache.juneau.assertions.Assertions.*;
import static org.apache.juneau.internal.ExceptionUtils.*;

import java.util.*;
import java.util.function.*;
import java.util.stream.*;

import org.apache.http.*;
import org.apache.http.util.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.http.HttpHeaders;
import org.apache.juneau.internal.*;
import org.apache.juneau.svl.*;

/**
 * An immutable list of HTTP headers.
 * {@review}
 *
 * <h5 class='figure'>Example</h5>
 * <p class='bcode w800'>
 * 	HeaderList <jv>headers</jv> = HeaderList
 * 		.<jsm>create</jsm>()
 * 		.append(Accept.<jsm>of</jsm>("text/xml"))
 * 		.append(<js>"Content-Type"</js>, ()-><jsm>getDynamicContentTypeFromSomewhere</jsm>())
 * 		.build();
 * </p>
 *
 * <p>
 * Convenience creators are provided for creating lists with minimal code:
 * <p class='bcode w800'>
 * 	HeaderList <jv>headers</jv> = HeaderList.<jsm>of</jsm>(Accept.<jsf>TEXT_XML</jsf>, ContentType.<jsf>TEXT_XML</jsf>);
 * </p>
 *
 * <p>
 * Header lists are immutable, but can be appended to using the {@link #copy()} method:
 * <p class='bcode w800'>
 * 	headers = headers
 * 		.copy()
 * 		.append(AcceptEncoding.<jsm>of</jsm>(<js>"identity"</js>))
 * 		.build();
 * </p>
 *
 * <p>
 * Static methods are provided on {@link HttpHeaders} to further simplify creation of header lists.
 * <p class='bcode w800'>
 * 	<jk>import static</jk> org.apache.juneau.http.HttpHeaders.*;
 *
 * 	HeaderList <jv>headers</jv> = <jsm>headerList</jsm>(<jsm>accept</jsm>(<js>"text/xml"</js>), <jsm>contentType</jsm>(<js>"text/xml"<js>));
 * </p>
 *
 * <p>
 * The builder class supports setting default header values (i.e. add a header to the list if it isn't otherwise in the list).
 * Note that this is different from simply setting a value twice as using default values will not overwrite existing
 * headers.
 * <br>The following example notes the distinction:
 *
 * <p class='bcode w800'>
 * 	<jv>headers</jv> = HeaderList
 * 		.<jsm>create</jsm>()
 * 		.set(Accept.<jsf>TEXT_PLAIN</jsf>)
 * 		.set(Accept.<jsf>TEXT_XML</jsf>)
 * 		.build();
 * 	<jsm>assertObject</jsm>(<jv>headers</jv>).isString(<js>"[Accept: text/xml]"</js>);
 *
 * 	<jv>headers</jv> = HeaderList
 * 		.create()
 * 		.set(Accept.<jsf>TEXT_PLAIN</jsf>)
 * 		.setDefault(Accept.<jsf>TEXT_XML</jsf>)
 * 		.build();
 * 	<jsm>assertObject</jsm>(<jv>headers</jv>).isString(<js>"[Accept: text/plain]"</js>);
 * </p>
 *
 * <p>
 * Various methods are provided for iterating over the headers in this list to avoid array copies.
 * <ul class='javatree'>
 * 	<li class='jm'>{@link #forEach(Consumer)} / {@link #forEach(String,Consumer)} - Use consumers to process headers.
 * 	<li class='jm'>{@link #iterator()} / {@link #iterator(String)} - Use an {@link HeaderIterator} to process headers.
 * 	<li class='jm'>{@link #stream()} / {@link #stream(String)} - Use a stream.
 * </ul>
 * <p>
 * In general, try to use these over the {@link #getAll()}/{@link #getAll(String)} methods that require array copies.
 *
 * <p>
 * The {@link #get(String)} method is special in that it will collapse multiple headers with the same name into
 * a single comma-delimited list (see <a href='https://tools.ietf.org/html/rfc2616#section-4.2'>RFC 2616 Section 4.2</a> for rules).
 *
 * <p>
 * The {@link #get(Class)} and {@link #get(String, Class)} methods are provided for working with {@link org.apache.juneau.http.annotation.Header}-annotated
 * beans.
 *
 * <h5 class='figure'>Example</h5>
 * <p class='bcode w800'>
 * 	ContentType <jv>contentType</jv> = <jv>headers</jv>.get(ContentType.<jk>class</jk>);
 * </p>
 *
 * <p>
 * By default, header names are treated as case-insensitive.  This can be changed using the {@link HeaderListBuilder#caseSensitive()}
 * method.
 *
 * <p>
 * A {@link VarResolver} can be associated with this builder to create header values with embedded variables that
 * are resolved at runtime.
 *
 * <h5 class='figure'>Example</h5>
 * <p class='bcode w800'>
 * 	<jc>// Create a header list with dynamically-resolving values pulled from a system property.</jc>
 *
 * 	System.<jsm>setProperty</jsm>(<js>"foo"</js>, <js>"bar"</js>);
 *
 * 	HeaderList <jv>headers</jv> = HeaderList
 * 		.<jsm>create</jsm>()
 * 		.resolving()
 * 		.append(<js>"X1"</js>, <js>"$S{foo}"</js>)
 * 		.append(<js>"X2"</js>, ()-><js>"$S{foo}"</js>)
 * 		.build();
 *
 * 	<jsm>assertObject</jsm>(<jv>headers</jv>).isString(<js>"[X1: bar, X2: bar]"</js>);
 * </p>
 *
 * <p>
 * The {@link HeaderList} object can be extended to defined pre-packaged lists of headers which can be used in various
 * annotations throughout the framework.
 *
 * <h5 class='figure'>Example</h5>
 * <p class='bcode w800'>
 * 	<jc>// A predefined list of headers.</jc>
 * 	<jk>public class</jk> MyHeaderList <jk>extends</jk> HeaderList {
 * 		<jk>public</jk> MyHeaderList() {
 * 			<jk>super</jk>(Accept.<jsf>TEXT_XML</jsf>, ContentType.<jsf>TEXT_XML</jsf>);
 * 		}
 * 	}
 *
 * 	<jc>// Use it on a remote proxy to add headers on all requests.</jc>
 *  <ja>@Remote</ja>(path=<js>"/petstore"</js>, headerList=MyHeaderList.<jk>class</jk>)
 * 	<jk>public interface</jk> PetStore {
 *
 * 		<ja>@RemotePost</ja>(<js>"/pets"</js>)
 * 		Pet addPet(
 * 			<ja>@Body</ja> CreatePet <jv>createPet</jv>,
 * 			<ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
 * 			<ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
 * 		);
 * 	}
 * </p>
 */
@ThreadSafe
public class HeaderList {

	private static final Header[] EMPTY_ARRAY = new Header[0];

	/** Represents no header supplier in annotations. */
	public static final class Null extends HeaderList {}

	/** Predefined instance. */
	public static final HeaderList EMPTY = new HeaderList();

	final Header[] entries;
	final boolean caseSensitive;

	/**
	 * Instantiates a new builder for this bean.
	 *
	 * @return A new builder.
	 */
	public static HeaderListBuilder create() {
		return new HeaderListBuilder();
	}

	/**
	 * Creates a new {@link HeaderList} initialized with the specified headers.
	 *
	 * @param headers
	 * 	The headers to add to the list.
	 * 	<br>Can be <jk>null</jk>.
	 * 	<br><jk>null</jk> entries are ignored.
	 * @return A new unmodifiable instance, never <jk>null</jk>.
	 */
	public static HeaderList of(List<Header> headers) {
		return headers == null || headers.isEmpty() ? EMPTY : new HeaderList(headers);
	}

	/**
	 * Creates a new {@link HeaderList} initialized with the specified headers.
	 *
	 * @param headers
	 * 	The headers to add to the list.
	 * 	<br><jk>null</jk> entries are ignored.
	 * @return A new unmodifiable instance, never <jk>null</jk>.
	 */
	public static HeaderList of(Header...headers) {
		return headers == null || headers.length == 0 ? EMPTY : new HeaderList(headers);
	}

	/**
	 * Creates a new {@link HeaderList} initialized with the specified name/value pairs.
	 *
	 * <h5 class='figure'>Example</h5>
	 * <p class='bcode w800'>
	 * 	HeaderList <jv>headers</jv> = HeaderList.<jsm>ofPairs</jsm>(<js>"Accept"</js>, <js>"text/xml"</js>, <js>"Content-Type"</js>, <js>"text/xml"</js>);
	 * </p>
	 *
	 * @param pairs
	 * 	Initial list of pairs.
	 * 	<br>Must be an even number of parameters representing key/value pairs.
	 * @throws RuntimeException If odd number of parameters were specified.
	 * @return A new instance.
	 */
	public static HeaderList ofPairs(String...pairs) {
		if (pairs == null || pairs.length == 0)
			return EMPTY;
		if (pairs.length % 2 != 0)
			throw runtimeException("Odd number of parameters passed into HeaderList.ofPairs()");
		ArrayBuilder<Header> b = ArrayBuilder.create(Header.class, pairs.length / 2, true);
		for (int i = 0; i < pairs.length; i+=2)
			b.add(BasicHeader.of(pairs[i], pairs[i+1]));
		return new HeaderList(b.toArray());
	}

	/**
	 * Constructor.
	 *
	 * @param builder The builder containing the settings for this bean.
	 */
	public HeaderList(HeaderListBuilder builder) {
		if (builder.defaultEntries == null) {
			entries = builder.entries.toArray(new Header[builder.entries.size()]);
		} else {
			ArrayBuilder<Header> l = ArrayBuilder.create(Header.class, builder.entries.size() + builder.defaultEntries.size(), true);

			for (int i = 0, j = builder.entries.size(); i < j; i++)
				l.add(builder.entries.get(i));

			for (int i1 = 0, j1 = builder.defaultEntries.size(); i1 < j1; i1++) {
				Header x = builder.defaultEntries.get(i1);
				boolean exists = false;
				for (int i2 = 0, j2 = builder.entries.size(); i2 < j2 && ! exists; i2++)
					exists = eq(builder.entries.get(i2).getName(), x.getName());
				if (! exists)
					l.add(x);
			}

			entries = l.toArray();
		}
		this.caseSensitive = builder.caseSensitive;
	}

	/**
	 * Constructor.
	 *
	 * @param headers
	 * 	The headers to add to the list.
	 * 	<br>Can be <jk>null</jk>.
	 * 	<br><jk>null</jk> entries are ignored.
	 */
	protected HeaderList(List<Header> headers) {
		ArrayBuilder<Header> l = ArrayBuilder.create(Header.class, headers.size(), true);
		for (int i = 0, j = headers.size(); i < j; i++)
			l.add(headers.get(i));
		entries = l.toArray();
		caseSensitive = false;
	}

	/**
	 * Constructor.
	 *
	 * @param headers
	 * 	The headers to add to the list.
	 * 	<br><jk>null</jk> entries are ignored.
	 */
	protected HeaderList(Header...headers) {
		ArrayBuilder<Header> l = ArrayBuilder.create(Header.class, headers.length, true);
		for (int i = 0; i < headers.length; i++)
			l.add(headers[i]);
		entries = l.toArray();
		caseSensitive = false;
	}

	/**
	 * Default constructor.
	 */
	protected HeaderList() {
		entries = EMPTY_ARRAY;
		caseSensitive = false;
	}

	/**
	 * Returns a builder initialized with the contents of this bean.
	 *
	 * @return A new builder object.
	 */
	public HeaderListBuilder copy() {
		return new HeaderListBuilder(this);
	}

	/**
	 * Gets a header representing all of the header values with the given name.
	 *
	 * <p>
	 * If more that one header with the given name exists the values will be combined with <js>", "</js> as per
	 * <a href='https://tools.ietf.org/html/rfc2616#section-4.2'>RFC 2616 Section 4.2</a>.
	 *
	 * @param name The header name.
	 * @return A header with a condensed value, or {@link Optional#empty()} if no headers by the given name are present
	 */
	public Optional<Header> get(String name) {

		Header first = null;
		List<Header> rest = null;
		for (int i = 0; i < entries.length; i++) {
			Header x = entries[i];
			if (eq(x.getName(), name)) {
				if (first == null)
					first = x;
				else {
					if (rest == null)
						rest = new ArrayList<>();
					rest.add(x);
				}
			}
		}

		if (first == null)
			return Optional.empty();

		if (rest == null)
			return Optional.of(first);

		CharArrayBuffer sb = new CharArrayBuffer(128);
		sb.append(first.getValue());
		for (int i = 0; i < rest.size(); i++) {
			sb.append(", ");
			sb.append(rest.get(i).getValue());
		}

		return Optional.of(new BasicHeader(name, sb.toString()));
	}

	/**
	 * Gets a header representing all of the header values with the given name.
	 *
	 * <p>
	 * If more that one header with the given name exists the values will be combined with <js>", "</js> as per
	 * <a href='https://tools.ietf.org/html/rfc2616#section-4.2'>RFC 2616 Section 4.2</a>.
	 *
	 * <p>
	 * The implementation class must have a public constructor taking in one of the following argument lists:
	 * <ul>
	 * 	<li><c>X(String <jv>value</jv>)</c>
	 * 	<li><c>X(Object <jv>value</jv>)</c>
	 * 	<li><c>X(String <jv>name</jv>, String <jv>value</jv>)</c>
	 * 	<li><c>X(String <jv>name</jv>, Object <jv>value</jv>)</c>
	 * </ul>
	 *
	 * <h5 class='figure'>Example</h5>
	 * <p class='bcode w800'>
	 * 	BasicIntegerHeader <jv>age</jv> = headerList.get(<js>"Age"</js>, BasicIntegerHeader.<jk>class</jk>);
	 * </p>
	 *
	 * @param name The header name.
	 * @param type The header implementation class.

	 * @return A header with a condensed value or <jk>null</jk> if no headers by the given name are present
	 */
	public <T> Optional<T> get(String name, Class<T> type) {

		Header first = null;
		List<Header> rest = null;
		for (int i = 0; i < entries.length; i++) {
			Header x = entries[i];
			if (eq(x.getName(), name)) {
				if (first == null)
					first = x;
				else {
					if (rest == null)
						rest = new ArrayList<>();
					rest.add(x);
				}
			}
		}

		if (first == null)
			return Optional.empty();

		if (rest == null)
			return Optional.of(HeaderBeanMeta.of(type).construct(name, first.getValue()));

		CharArrayBuffer sb = new CharArrayBuffer(128);
		sb.append(first.getValue());
		for (int i = 0; i < rest.size(); i++) {
			sb.append(", ");
			sb.append(rest.get(i).getValue());
		}

		return Optional.of(HeaderBeanMeta.of(type).construct(name, sb.toString()));
	}

	/**
	 * Gets a header representing all of the header values with the given name.
	 *
	 * <p>
	 * Same as {@link #get(String, Class)} but the header name is pulled from the {@link org.apache.juneau.http.annotation.Header#name()} or
	 * 	{@link org.apache.juneau.http.annotation.Header#value()} annotations.
	 *
	 * <h5 class='figure'>Example</h5>
	 * <p class='bcode w800'>
	 * 	Age <jv>age</jv> = headerList.get(Age.<jk>class</jk>);
	 * </p>
	 *
	 * @param type The header implementation class.
	 * @return A header with a condensed value or <jk>null</jk> if no headers by the given name are present
	 */
	public <T> Optional<T> get(Class<T> type) {
		assertArgNotNull("type", type);

		String name = HeaderBeanMeta.of(type).getSchema().getName();
		if (name == null)
			throw new BasicIllegalArgumentException("Header name could not be found on bean type ''{0}''", type.getName());

		return get(name, type);
	}

	/**
	 * Gets all of the headers with the given name.
	 *
	 * <p>
	 * The returned array maintains the relative order in which the headers were added.
	 *
	 * <p>
	 * Header name comparison is case insensitive.
	 *
	 * @param name The header name.
	 *
	 * @return An array containing all matching headers, or an empty array if none are found.
	 */
	public Header[] getAll(String name) {
		List<Header> l = null;
		for (int i = 0; i < entries.length; i++) {
			Header x = entries[i];
			if (eq(x.getName(), name)) {
				if (l == null)
					l = new ArrayList<>();
				l.add(x);
			}
		}
		return l == null ? EMPTY_ARRAY : l.toArray(new Header[l.size()]);
	}

	/**
	 * Returns the number of headers in this list.
	 *
	 * @return The number of headers in this list.
	 */
	public int size() {
		return entries.length;
	}

	/**
	 * Gets the first header with the given name.
	 *
	 * <p>
	 * Header name comparison is case insensitive.
	 *
	 * @param name The header name.
	 * @return The first matching header, or <jk>null</jk> if not found.
	 */
	public Optional<Header> getFirst(String name) {
		for (int i = 0; i < entries.length; i++) {
			Header x = entries[i];
			if (eq(x.getName(), name))
				return Optional.of(x);
		}
		return Optional.empty();
	}

	/**
	 * Gets the last header with the given name.
	 *
	 * <p>
	 * Header name comparison is case insensitive.
	 *
	 * @param name The header name.
	 * @return The last matching header, or <jk>null</jk> if not found.
	 */
	public Optional<Header> getLast(String name) {
		for (int i = entries.length - 1; i >= 0; i--) {
			Header x = entries[i];
			if (eq(x.getName(), name))
				return Optional.of(x);
		}
		return Optional.empty();
	}

	/**
	 * Gets all of the headers contained within this list.
	 *
	 * @return An array of all the headers in this list, or an empty array if no headers are present.
	 */
	public Header[] getAll() {
		return entries.length == 0 ? EMPTY_ARRAY : Arrays.copyOf(entries, entries.length);
	}

	/**
	 * Tests if headers with the given name are contained within this list.
	 *
	 * <p>
	 * Header name comparison is case insensitive.
	 *
	 * @param name The header name.
	 * @return <jk>true</jk> if at least one header with the name is present.
	 */
	public boolean contains(String name) {
		for (int i = 0; i < entries.length; i++) {
			Header x = entries[i];
			if (eq(x.getName(), name))
				return true;
		}
		return false;
	}

	/**
	 * Returns an iterator over this list of headers.
	 *
	 * @return A new iterator over this list of headers.
	 */
	public HeaderIterator iterator() {
		return new BasicHeaderIterator(entries, null, caseSensitive);
	}

	/**
	 * Returns an iterator over the headers with a given name in this list.
	 *
	 * @param name The name of the headers over which to iterate, or <jk>null</jk> for all headers
	 *
	 * @return A new iterator over the matching headers in this list.
	 */
	public HeaderIterator iterator(String name) {
		return new BasicHeaderIterator(entries, name, caseSensitive);
	}

	/**
	 * Performs an operation on the headers of this list.
	 *
	 * <p>
	 * This is the preferred method for iterating over headers as it does not involve
	 * creation or copy of lists/arrays.
	 *
	 * @param c The consumer.
	 * @return This object (for method chaining).
	 */
	public HeaderList forEach(Consumer<Header> c) {
		for (int i = 0; i < entries.length; i++)
			c.accept(entries[i]);
		return this;
	}

	/**
	 * Performs an operation on the headers with the specified name in this list.
	 *
	 * <p>
	 * This is the preferred method for iterating over headers as it does not involve
	 * creation or copy of lists/arrays.
	 *
	 * @param name The header name.
	 * @param c The consumer.
	 * @return This object (for method chaining).
	 */
	public HeaderList forEach(String name, Consumer<Header> c) {
		for (int i = 0; i < entries.length; i++)
			if (eq(name, entries[i].getName()))
				c.accept(entries[i]);
		return this;
	}

	/**
	 * Returns a stream of the headers in this list.
	 *
	 * <p>
	 * This does not involve a copy of the underlying array of <c>Header</c> objects so should perform well.
	 *
	 * @return This object (for method chaining).
	 */
	public Stream<Header> stream() {
		return Arrays.stream(entries);
	}

	/**
	 * Returns a stream of the headers in this list with the specified name.
	 *
	 * <p>
	 * This does not involve a copy of the underlying array of <c>Header</c> objects so should perform well.
	 *
	 * @param name The header name.
	 * @return This object (for method chaining).
	 */
	public Stream<Header> stream(String name) {
		return Arrays.stream(entries).filter(x->eq(name, x.getName()));
	}

	private boolean eq(String s1, String s2) {
		return StringUtils.eq(!caseSensitive, s1, s2);
	}

	@Override /* Object */
	public String toString() {
		return Arrays.asList(entries).toString();
	}
}
