/*=============================================================================#
 # Copyright (c) 2019, 2020 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.internal.rhelp.core.http;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.function.IntPredicate;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.eclipse.statet.jcommons.collections.BasicImMapEntry;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.collections.ImMapEntry;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;


@NonNullByDefault
public class HttpHeaderUtils {
	
	
	public static final String LOCATION_NAME= "Location"; //$NON-NLS-1$
	
	public static final String ACCEPT_NAME= "Accept"; //$NON-NLS-1$
	
	public static final String QUALITY_FACTOR_PARAM_NAME= "q"; //$NON-NLS-1$
	
	
	public static class MediaTypeEntry extends BasicMediaType implements Comparable<MediaTypeEntry> {
		
		
		private final float qualityFactor;
		
		
		public MediaTypeEntry(final String type, final String subtype,
				final float qualityFactor, final ImList<? extends ImMapEntry<String, String>> extParams) {
			super(type, subtype, extParams);
			this.qualityFactor= qualityFactor;
		}
		
		
		public float getQualityFactor() {
			return this.qualityFactor;
		}
		
		
		@Override
		public int compareTo(final MediaTypeEntry o) {
			{	final float diff= this.qualityFactor - o.qualityFactor;
				if (diff != 0) {
					return (diff > 0) ? -1 : 1;
				}
			}
			{	final int diff= compare(getType(), o.getType());
				if (diff != 0) {
					return diff;
				}
			}
			{	final int diff= compare(getSubtype(), o.getSubtype());
				if (diff != 0) {
					return diff;
				}
			}
			return -(getParameters().size() - o.getParameters().size());
		}
		
		
	}
	
	public static class ParseException extends Exception {
		
		private static final long serialVersionUID= 1L;
		
		private final String errorDescription;
		private final String input;
		private final int errorOffset;
		
		public ParseException(final String errorDescription, final String input, final int errorOffset) {
			super(String.format("Parse error: %1$s at %3$s in:\n%2$s", errorDescription, input, errorOffset));
			this.errorDescription= errorDescription;
			this.input= input;
			this.errorOffset= errorOffset;
		}
		
		
		public String getErrorDescription() {
			return this.errorDescription;
		}
		
		public String getInput() {
			return this.input;
		}
		
		public int getErrorOffset() {
			return this.errorOffset;
		}
		
	}
	
	public static final class HeaderBuilder {
		
		
		private final StringBuilder sb= new StringBuilder();
		
		
		public HeaderBuilder() {
		}
		
		
		public void newEntry(final String value) {
			if (this.sb.length() > 0) {
				this.sb.append(',');
			}
			this.sb.append(value);
		}
		
		public void newEntry(final String value, final float qValue) {
			newEntry(value);
			this.sb.append(';');
			this.sb.append(QUALITY_FACTOR_PARAM_NAME);
			this.sb.append('=');
			this.sb.append(qValue);
		}
		
		public void addParameter(final String name, final String value) {
			this.sb.append(';');
			this.sb.append(name);
			this.sb.append('=');
			this.sb.append(value);
		}
		
		public String build() {
			return this.sb.toString();
		}
		
	}
	
	
	private static class Tokenizer {
		
		private static boolean isLinearWhitespace(final char c) {
			switch (c) {
			case ' ':
			case '\t':
			case '\r':
			case '\n':
				return true;
			default:
				return false;
			}
		}
		
		private static boolean isSeparator(final char c) {
			switch (c) {
			case '(':
			case ')':
			case '<':
			case '>':
			case '@':
			case ',':
			case ';':
			case ':':
			case '\\':
			case '"':
			case '/':
			case '[':
			case ']':
			case '?':
			case '=':
			case '{':
			case '}':
			case ' ':
			case '\t':
				return true;
			default:
				return false;
			}
		}
		
		private final String input;
		
		private int index;
		
		
		public Tokenizer(final String input) {
			this.input= input;
		}
		
		
		private int consumeWhitespace(int idx) {
			while (idx < this.input.length() && isLinearWhitespace(this.input.charAt(idx))) {
				idx++;
			}
			return idx;
		}
		
		private int consumeToken(int idx) {
			while (idx < this.input.length()) {
				final char c= this.input.charAt(idx);
				if (c > 0x20 && c < 0x7F && !isSeparator(c)) {
					idx++;
				}
				else {
					break;
				}
			}
			return idx;
		}
		
		public void readOperatorAssert(final char c) throws ParseException {
			int idx= this.index;
			idx= consumeWhitespace(idx);
			if (idx < this.input.length() && this.input.charAt(idx) == c) {
				this.index= idx + 1;
				return;
			}
			throw new ParseException("operator '" + c + "' expected", this.input, idx);
		}
		
		public String readTokenAssert() throws ParseException {
			int idx= this.index;
			idx= consumeWhitespace(idx);
			final int start= idx;
			idx= consumeToken(idx);
			if (start < idx) {
				this.index= idx;
				return this.input.substring(start, idx);
			}
			throw new ParseException("token expected", this.input, idx);
		}
		
		private String readParamValue(int idx) throws ParseException {
			if (idx < this.input.length()) {
				if (this.input.charAt(idx) == '"') {
					idx++;
					final int start= idx;
					int end= -1;
					while (idx < this.input.length()) {
						final char c= this.input.charAt(idx);
						switch (c) {
						case '"':
							end= idx;
							idx++;
							break;
						case '\\':
							idx++;
							if (idx < this.input.length()) {
								idx++;
							}
							continue;
						default:
							idx++;
							continue;
						}
					}
					this.index= idx;
					if (end >= 0) {
						return this.input.substring(start, end);
					}
					throw new ParseException("closing quote ('\"') expected", this.input, idx);
				}
				else {
					final int start= idx;
					idx= consumeToken(idx);
					this.index= idx;
					return this.input.substring(start, idx);
				}
			}
			this.index= idx;
			return "";
		}
		
		public String readParamValue() throws ParseException {
			int idx= this.index;
			idx= consumeWhitespace(idx);
			return readParamValue(idx);
		}
		
		public void skipParamValue() throws ParseException {
			int idx= this.index;
			idx= consumeWhitespace(idx);
			if (idx < this.input.length()) {
				if (this.input.charAt(idx) == '"') {
					idx++;
					int end= -1;
					while (idx < this.input.length()) {
						final char c= this.input.charAt(idx);
						switch (c) {
						case '"':
							end= idx;
							idx++;
							break;
						case '\\':
							idx++;
							if (idx < this.input.length()) {
								idx++;
							}
							continue;
						default:
							idx++;
							continue;
						}
					}
					this.index= idx;
					if (end >= 0) {
						return;
					}
					throw new ParseException("closing quote ('\"') expected", this.input, idx);
				}
				else {
					idx= consumeToken(idx);
					this.index= idx;
					return;
				}
			}
			this.index= idx;
		}
		
		public float readQValue() throws ParseException {
			int idx= this.index;
			idx= consumeWhitespace(idx);
			final int start= idx;
			try {
				idx= consumeToken(idx);
				this.index= idx;
				return Float.parseFloat(this.input.substring(start, idx));
			}
			catch (final NumberFormatException e) {
				throw new ParseException("q value (number) expected", this.input, start);
			}
		}
		
		public boolean readNextEntry() {
			int idx= this.index;
			idx= consumeWhitespace(idx);
			if (idx < this.input.length()) {
				if (this.index == 0) {
					return true;
				}
				if (this.input.charAt(idx) == ',') {
					this.index= idx + 1;
					return true;
				}
			}
			this.index= idx;
			return false;
		}
		
		public boolean readNextParam() {
			int idx= this.index;
			idx= consumeWhitespace(idx);
			if (idx < this.input.length() && this.input.charAt(idx) == ';') {
				this.index= idx + 1;
				return true;
			}
			this.index= idx;
			return false;
		}
		
		public void assertEnd() throws ParseException {
			int idx= this.index;
			idx= consumeWhitespace(idx);
			this.index= idx;
			if (idx == this.input.length()) {
				return;
			}
			throw new ParseException("EOF expected", this.input, idx);
		}
		
	}
	
	public static List<MediaTypeEntry> readAcceptHeaderEntries(final HttpServletRequest req,
			final @Nullable BiPredicate<String, String> filter)
			throws ServletException {
		try {
			final List<MediaTypeEntry> entries= new ArrayList<>();
			final Enumeration<String> headers= req.getHeaders(ACCEPT_NAME);
			if (headers != null) {
				parseMediaTypes(headers, filter, entries);
			}
			entries.sort(null);
			return entries;
		}
		catch (final ParseException e) {
			throw new ServletException("Failed to read Accept header of request.", e);
		}
	}
	
	public static List<MediaTypeEntry> readMediaTypeEntries(final Collection<String> headers,
			final @Nullable BiPredicate<String, String> filter)
			throws ParseException {
		final List<MediaTypeEntry> entries= new ArrayList<>();
		if (!headers.isEmpty()) {
			parseMediaTypes(Collections.enumeration(headers), filter, entries);
		}
		entries.sort(null);
		return entries;
	}
	
	protected final static void parseMediaTypes(final Enumeration<String> headers,
			final @Nullable BiPredicate<String, String> filter, final List<MediaTypeEntry> entries) throws ParseException {
		final List<ImMapEntry<String, String>> extParams= new ArrayList<>();
		while (headers.hasMoreElements()) {
			final Tokenizer tokenizer= new Tokenizer(headers.nextElement());
			while (tokenizer.readNextEntry()) {
				extParams.clear();
				
				final String type= tokenizer.readTokenAssert();
				tokenizer.readOperatorAssert('/');
				final String subtype= tokenizer.readTokenAssert();
				
				final boolean include= (filter == null || filter.test(type, subtype));
				float qValue= 1;
				for (int nParam= 0; tokenizer.readNextParam(); nParam++) {
					final String paramName= tokenizer.readTokenAssert();
					tokenizer.readOperatorAssert('=');
					if (!include) {
						tokenizer.skipParamValue();
						continue;
					}
					if (nParam == 0 && paramName.equals(QUALITY_FACTOR_PARAM_NAME)) {
						qValue= tokenizer.readQValue();
					}
					else {
						final String paramValue= tokenizer.readParamValue();
						extParams.add(new BasicImMapEntry<>(paramName, paramValue));
					}
				}
				entries.add(new MediaTypeEntry(type, subtype, qValue,
						ImCollections.toList(extParams) ));
			}
			tokenizer.assertEnd();
		}
	}
	
	
	public static int findFirstValid(final List<MediaTypeEntry> entries,
			final String parameterName, final IntPredicate paramPredicate) {
		for (final MediaTypeEntry entry : entries) {
			final String vString= entry.getParameterValue(parameterName);
			if (vString != null) {
				try {
					final int v= Integer.parseInt(vString);
					if (paramPredicate.test(v)) {
						return v;
					}
				}
				catch (final NumberFormatException e) {}
			}
		}
		return -1;
	}
	
}
