/*=============================================================================#
 # Copyright (c) 2008, 2021 IBM Corporation 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.
 # 
 # SPDX-License-Identifier: EPL-2.0
 # 
 # Contributors:
 #     IBM Corporation - org.eclipse.jdt: initial API and implementation
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.ltk.ui.sourceediting;

import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.ui.texteditor.MarkerAnnotation;
import org.eclipse.ui.texteditor.MarkerUtilities;
import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;

import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.collections.ImSet;
import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;

import org.eclipse.statet.ltk.core.Ltk;
import org.eclipse.statet.ltk.issues.core.Issue;
import org.eclipse.statet.ltk.issues.core.IssueRequestor;
import org.eclipse.statet.ltk.issues.core.IssueTypeSet;
import org.eclipse.statet.ltk.issues.core.IssueTypeSet.IssueCategory;
import org.eclipse.statet.ltk.issues.core.IssueTypeSet.ProblemCategory;
import org.eclipse.statet.ltk.issues.core.IssueTypeSet.TaskCategory;
import org.eclipse.statet.ltk.issues.core.Problem;
import org.eclipse.statet.ltk.issues.core.impl.BasicIssueRequestor;


/**
 * Abstract annotation model dealing with marker annotations and temporary problems.
 * Also acts as problem requester for its source unit.
 */
@NonNullByDefault
public abstract class SourceAnnotationModel extends ResourceMarkerAnnotationModel {
	
	
	private static class PositionMap<V> implements Iterable<PositionMap.Entry<V>> {
		
		static class Entry<V> {
			
			final Position position;
			
			ImList<V> annotations;
			
			public Entry(final Position position, final V value) {
				this.position= position;
				this.annotations= ImCollections.newList(value);
			}
			
		}
		
		
		private final List<Entry<V>> list= new ArrayList<>();
		private int anchor= 0;
		
		
		public PositionMap() {
		}
		
		
		private int indexOf(final Position position) {
			final int length= this.list.size();
			for (int i= 0; i < length; i++) {
				final var entry= this.list.get(i);
				if (entry.position.equals(position)) {
					return i;
				}
			}
			return -1;
		}
		
		public @Nullable ImList<V> get(final Position position) {
			final int length= this.list.size();
			// behind anchor
			for (int i= this.anchor; i < length; i++) {
				final var entry= this.list.get(i);
				if (entry.position.equals(position)) {
					this.anchor= i;
					return entry.annotations;
				}
			}
			// before anchor
			for (int i= 0; i < this.anchor; i++) {
				final var entry= this.list.get(i);
				if (entry.position.equals(position)) {
					this.anchor= i;
					return entry.annotations;
				}
			}
			return null;
		}
		
		@Override
		public Iterator<Entry<V>> iterator() {
			return this.list.iterator();
		}
		
		public void add(final Position position, final V value) {
			final int index= indexOf(position);
			if (index >= 0) {
				final var entry= this.list.get(index);
				entry.annotations= ImCollections.addElement(entry.annotations, value);
			}
			else {
				this.list.add(new Entry<>(position, value));
			}
		}
		
		public void remove(final Position position, final Object value) {
			final int index= indexOf(position);
			if (index >= 0) {
				final var entry= this.list.get(index);
				entry.annotations= ImCollections.removeElement(entry.annotations, value);
				if (entry.annotations.isEmpty()) {
					this.list.remove(index);
				}
			}
		}
		
		public void clear() {
			this.list.clear();
		}
		
	}
	
	
	protected class SourceAnnotationIssueRequestor extends BasicIssueRequestor {
		
		
		public SourceAnnotationIssueRequestor(final IssueTypeSet issueTypeSet) {
			super(issueTypeSet, Ltk.EDITOR_CONTEXT);
		}
		
		
		@Override
		protected boolean shouldAccept(final ProblemCategory category) {
			return isHandlingTemporaryProblems(category);
		}
		
		@Override
		protected boolean shouldAccept(final TaskCategory category) {
			return false;
		}
		
		
		@Override
		protected void reportIssues(final @Nullable TaskBatch taskBatch,
				final ImList<ProblemBatch> problemBatches)
				throws CoreException {
			SourceAnnotationModel.this.reportIssues(problemBatches);
		}
		
	}
	
	
	private final IssueTypeSet issueTypeSet;
	
	private final AtomicInteger reportingCounter= new AtomicInteger();
	
	private final List<SourceIssueEditorAnnotation> editorAnnotations= new ArrayList<>();
	
	private final PositionMap<SourceIssueMarkerAnnotation<?>> markerAnnotations= new PositionMap<>();
	
	private @Nullable ImSet<IssueCategory<?>> reportedConfig;
	private List<SourceIssueMarkerAnnotation<?>> overlaidMarkerAnnotations= new ArrayList<>();
	
	
	public SourceAnnotationModel(final IResource resource, final IssueTypeSet issueTypeSet) {
		super(resource);
		this.issueTypeSet= issueTypeSet;
	}
	
	
	protected IssueTypeSet getIssueTypeSet() {
		return this.issueTypeSet;
	}
	
	
	protected abstract boolean isHandlingTemporaryProblems(ProblemCategory issueCategory);
	
	
	@Override
	protected @Nullable MarkerAnnotation createMarkerAnnotation(final IMarker marker) {
		String markerType= MarkerUtilities.getMarkerType(marker);
		if (markerType != null) {
			markerType= markerType.intern();
			final var issueCategory= this.issueTypeSet.getCategory(Ltk.PERSISTENCE_CONTEXT, markerType);
			if (issueCategory != null) {
				final var annotationType= issueCategory.mapType(Ltk.PERSISTENCE_CONTEXT, Ltk.EDITOR_CONTEXT,
						markerType );
				if (annotationType != null) {
					return new SourceIssueMarkerAnnotation<>(issueCategory, annotationType, marker);
				}
			}
		}
		return super.createMarkerAnnotation(marker);
	}
	
//	@Override
//	protected AnnotationModelEvent createAnnotationModelEvent() {
//		return new CompilationUnitAnnotationModelEvent(this, getResource());
//	}
	
	public final IssueRequestor createIssueRequestor() {
		this.reportingCounter.incrementAndGet();
		return doCreateIssueRequestor();
	}
	
	protected IssueRequestor doCreateIssueRequestor() {
		return new SourceAnnotationIssueRequestor(getIssueTypeSet());
	}
	
	private void reportIssues(final ImList<BasicIssueRequestor.ProblemBatch> problemBatches) {
		synchronized (getLockObject()) {
			if (this.reportingCounter.decrementAndGet() != 0) {
				return;
			}
			
			{	final Set<IssueCategory<?>> prevConfig= this.reportedConfig;
				final @NonNull IssueCategory<?>[] enabledCagetories= new  @NonNull IssueCategory[problemBatches.size()];
				int numEnabled= 0;
				for (final var problemBatch : problemBatches) {
					final var issueCategory= problemBatch.getCategory();
					if (problemBatch.isEnabled()) {
						enabledCagetories[numEnabled++]= issueCategory;
						if (prevConfig != null && !prevConfig.contains(issueCategory)) {
							resetMarkerAnnotationsControl(issueCategory, true);
						}
					}
					else {
						if (prevConfig != null && prevConfig.contains(issueCategory)) {
							resetMarkerAnnotationsControl(issueCategory, false);
						}
					}
				}
				this.reportedConfig= ImCollections.newIdentitySet(enabledCagetories, 0, numEnabled);
			}
			
			final var prevControlledAnnotations= this.overlaidMarkerAnnotations;
			this.overlaidMarkerAnnotations= new ArrayList<>();
			
			if (this.editorAnnotations.size() > 0) {
				removeAnnotations(this.editorAnnotations, false, true);
				this.editorAnnotations.clear();
			}
			
			for (final var problemBatch : problemBatches) {
				final var problemTypes= nonNullAssert(
						problemBatch.getCategory().getTypes(Ltk.EDITOR_CONTEXT) );
				if (problemBatch.isEnabled()) {
					for (final Problem problem : problemBatch.getAcceptedIssues()) {
						final Position position= createPosition(problem);
						if (position != null) {
							try {
								final var annotation= new SourceIssueEditorAnnotation(
										problemBatch.getCategory(),
										problemTypes.getType(problem.getSeverity()),
										problem );
								installMarkerAnnotationOverlays(position, annotation);
								addAnnotation(annotation, position, false);
								this.editorAnnotations.add(annotation);
							}
							catch (final BadLocationException x) {
							}
						}
					}
				}
			}
			
			if (prevControlledAnnotations != null && !prevControlledAnnotations.isEmpty()) {
				prevControlledAnnotations.removeAll(this.overlaidMarkerAnnotations);
				for (final var problemBatch : problemBatches) {
					if (problemBatch.isEnabled()) {
						removeMarkerAnnotationOverlays(prevControlledAnnotations,
								problemBatch.getCategory() );
					}
				}
			}
		}
		
		fireModelChanged();
	}
	
	
	protected Position createPosition(final Issue issue) {
		final int start= issue.getSourceStartOffset();
		final int end= issue.getSourceEndOffset();
		if (start < 0 && end < 0) {
			assert (start >= 0 && end >= 0);
		}
		return new Position(start, end-start);
	}
	
	
	private void installMarkerAnnotationOverlays(final Position position,
			final SourceIssueEditorAnnotation problemAnnotation) {
		final var annotations= this.markerAnnotations.get(position);
		if (annotations != null) {
			final var issueCategory= problemAnnotation.getIssueCategory();
			for (final var markerAnnotation : annotations) {
				if (markerAnnotation.getIssueCategory() == issueCategory) {
					markerAnnotation.setOverlay(problemAnnotation);
					this.overlaidMarkerAnnotations.add(markerAnnotation);
				}
			}
		}
	}
	
	private void removeMarkerAnnotationOverlays(final List<SourceIssueMarkerAnnotation<?>> annotations,
			final IssueCategory<?> issueCategory) {
		for (final var markerAnnotation : annotations) {
			if (markerAnnotation.getIssueCategory() == issueCategory) {
				markerAnnotation.setOverlay(null);
			}
		}
	}
	
	private void resetMarkerAnnotationsControl(final IssueCategory<?> issueCategory,
			final boolean isControlled) {
		final var modelEvent= getAnnotationModelEvent();
		if (isControlled) {
			for (final var entry : this.markerAnnotations) {
				for (final var markerAnnotation : entry.annotations) {
					if (markerAnnotation.getIssueCategory() == issueCategory
							&& !markerAnnotation.isControlled()) {
						markerAnnotation.setOverlay(null);
						modelEvent.annotationChanged(markerAnnotation);
					}
				}
			}
		}
		else {
			for (final var entry : this.markerAnnotations) {
				for (final var markerAnnotation : entry.annotations) {
					if (markerAnnotation.getIssueCategory() == issueCategory
							&& markerAnnotation.isControlled()) {
						markerAnnotation.disableOverlay();
						modelEvent.annotationChanged(markerAnnotation);
					}
				}
			}
		}
	}
	
	
	@Override
	protected void addAnnotation(final Annotation annotation, final Position position,
			final boolean fireModelChanged) throws BadLocationException {
		if (annotation instanceof SourceIssueMarkerAnnotation) {
			final var markerAnnotation= (SourceIssueMarkerAnnotation<?>)annotation;
			synchronized (getLockObject()) {
				final var config= this.reportedConfig;
				if (config != null && config.contains(markerAnnotation.getIssueCategory())) {
					markerAnnotation.setOverlay(null);
					this.overlaidMarkerAnnotations.add(markerAnnotation); // force check
				}
				this.markerAnnotations.add(position, markerAnnotation);
			}
		}
		
		super.addAnnotation(annotation, position, fireModelChanged);
	}
	
	@Override
	protected void removeAnnotation(final Annotation annotation, final boolean fireModelChanged) {
		if (annotation instanceof SourceIssueMarkerAnnotation) {
			final var markerAnnotation= (SourceIssueMarkerAnnotation<?>)annotation;
			final var position= getPosition(markerAnnotation);
			if (position != null) {
				synchronized (getLockObject()) {
					if (markerAnnotation.isControlled()) {
						markerAnnotation.disableOverlay();
					}
					this.markerAnnotations.remove(position, markerAnnotation);
				}
			}
		}
		
		super.removeAnnotation(annotation, fireModelChanged);
	}
	
	@Override
	protected void removeAllAnnotations(final boolean fireModelChanged) {
		super.removeAllAnnotations(fireModelChanged);
		
		synchronized (getLockObject()) {
			this.markerAnnotations.clear();
		}
	}
	
}
