/*=============================================================================#
 # Copyright (c) 2017, 2018 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.rj.server.dbg;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.eclipse.statet.jcommons.collections.CollectionUtils;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;


@NonNullByDefault
public final class Tracepoints {
	
	
	public static final Logger LOGGER= Logger.getLogger("org.eclipse.statet.rj.server.dbg"); //$NON-NLS-1$
	
	
	public static final String TOPLEVEL_ELEMENT_ID= "200:"; //$NON-NLS-1$
	
	
	public static final int indexOfTracepointById(final List<? extends Tracepoint> entries,
			final long id) {
		for (int idx= 0; idx < entries.size(); idx++) {
			if (entries.get(idx).getId() == id) {
				return idx;
			}
		}
		return -1;
	}
	
	
	public static final boolean containsPositionsById(final List<? extends TracepointPosition> list,
			final List<? extends TracepointPosition> requiredIds) {
		if (list == requiredIds) {
			return true;
		}
		final int l= requiredIds.size();
		if (list.size() < l) {
			return false;
		}
		ITER_REQUIRED: for (int i= 0, j= 0; i < l; i++) {
			final long id= requiredIds.get(i).getId();
			while (j < list.size()) {
				if (list.get(j++).getId() == id) {
					continue ITER_REQUIRED;
				}
			}
			return false;
		}
		return true;
	}
	
	public static final boolean equalsPositions(
			final List<? extends TracepointPosition> list1, final List<? extends TracepointPosition> list2,
			final List<? extends TracepointPosition> requiredIds) {
		if (list1 == list2) {
			return true;
		}
		final int l= list1.size();
		if (l != list2.size()) {
			return false;
		}
		ITER_REQUIRED: for (int i= 0, j1= 0, j2= 0; i < l; i++) {
			final long id= requiredIds.get(i).getId();
			while (j1 < list1.size()) {
				final TracepointPosition p1= list1.get(j1++);
				if (p1.getId() == id) {
					while (j2 < list2.size()) {
						final TracepointPosition p2= list1.get(j2++);
						if (p2.getId() == id) {
							if (p1.equals(p2)) {
								continue ITER_REQUIRED;
							}
							return false;
						}
					}
					return false;
				}
			}
			return false;
		}
		return true;
	}
	
	public static final List<TracepointPosition> filterPositionsById(final List<? extends TracepointPosition> list,
			final List<? extends TracepointPosition> requiredIds) {
		final int l= requiredIds.size();
		if (list.size() == l) {
			return ImCollections.toList(list);
		}
		final TracepointPosition[] array= new @NonNull TracepointPosition[l];
		ITER_REQUIRED: for (int i= 0, j= 0; i < l; i++) {
			final long id= requiredIds.get(i).getId();
			while (j < list.size()) {
				final TracepointPosition p= list.get(j++);
				if (p.getId() == id) {
					array[i]= p;
					continue ITER_REQUIRED;
				}
			}
			throw new IllegalArgumentException("TracepointPosition missing: id= " + id); //$NON-NLS-1$
		}
		return ImCollections.newList(array);
	}
	
	public static final List<TracepointPosition> intersectPositionsById(final List<? extends TracepointPosition> list,
			final List<? extends TracepointPosition> includedIds) {
		final int l= includedIds.size();
		final List<TracepointPosition> intersection= new ArrayList<>(l);
		ITER_INCLUDED: for (int i= 0, j= 0; i < l; i++) {
			final long id= includedIds.get(i).getId();
			int j0= j;
			while (j0 < list.size()) {
				final TracepointPosition p= list.get(j0++);
				if (p.getId() == id) {
					intersection.add(p);
					j= j0;
					continue ITER_INCLUDED;
				}
			}
		}
		return intersection;
	}
	
	public static final List<TracepointPosition> intersectPositionsById(final List<? extends TracepointPosition> list,
			final long[] includedIds) {
		final int l= includedIds.length;
		final List<TracepointPosition> intersection= new ArrayList<>(l);
		ITER_INCLUDED: for (int i= 0, j= 0; i < l; i++) {
			final long id= includedIds[i];
			int j0= j;
			while (j0 < list.size()) {
				final TracepointPosition p= list.get(j0++);
				if (p.getId() == id) {
					intersection.add(p);
					j= j0;
					continue ITER_INCLUDED;
				}
			}
		}
		return intersection;
	}
	
	
	private static final char[] DIGITS= new char[] {
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
	};
	
	public static final String toString(long id) {
		final char[] c= new char[16];
		for (int i= 0; i < 16; i++) {
			c[15 - i]= DIGITS[(int) id & 0xF];
			id >>>= 4;
		}
		return new String(c, 0, 16);
	}
	
	public static final void append(long id, final StringBuilder sb) {
		final char[] c= new char[16];
		for (int i= 0; i < 16; i++) {
			c[15 - i]= DIGITS[(int) id & 0xF];
			id >>>= 4;
		}
		sb.append(c);
	}
	
	
	public static final String toLogString(final List<? extends TracepointPosition> positions) {
		final int n= positions.size();
		if (n <= 0) {
			return ""; //$NON-NLS-1$
		}
		if (LOGGER.isLoggable(Level.FINEST)) {
			return "\n\t\t" + CollectionUtils.toString(positions, "\n\t\t");
		}
		else {
			final StringBuilder sb= new StringBuilder(n * 18);
			sb.append(positions.get(0).getId());
			for (int i= 1; i < n; i++) {
				sb.append(", ");
				append(positions.get(i).getId(), sb);
			}
			return sb.toString();
		}
	}
	
	
	private Tracepoints() {}
	
}
