/*=============================================================================#
 # Copyright (c) 2005, 2021 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.ecommons.text.core.util;

import java.util.ArrayList;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.AbstractDocument;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPartitioningException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.IDocumentPartitionerExtension2;
import org.eclipse.jface.text.IDocumentPartitioningListener;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TypedRegion;

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.jcommons.text.core.TextRegion;

import org.eclipse.statet.ecommons.text.core.FragmentDocument;
import org.eclipse.statet.ecommons.text.core.JFaceTextRegion;
import org.eclipse.statet.internal.ecommons.text.core.ECommonsTextCorePlugin;


/**
 * @since de.walware.ecommons.text 1.1
 */
@NonNullByDefault
public abstract class AbstractFragmentDocument extends AbstractSynchronizableDocument
		implements FragmentDocument {
	
	
	private static final byte NO_CHANGE= 0;
	private static final byte PREFIX_CHANGE= 1;
	private static final byte FRAGMENT_CHANGE= 2;
	
	
	private class PartitionerMapper implements IDocumentPartitioner {
		
		private final IDocumentPartitioner masterPartitioner;
		
		public PartitionerMapper(final IDocumentPartitioner partitioner) {
			this.masterPartitioner= partitioner;
		}
		
		@Override
		public void connect(final IDocument document) {
			throw new UnsupportedOperationException();
		}
		
		@Override
		public void disconnect() {
			throw new UnsupportedOperationException();
		}
		
		@Override
		public void documentAboutToBeChanged(final DocumentEvent event) {
			throw new UnsupportedOperationException();
		}
		
		@Override
		public boolean documentChanged(final DocumentEvent event) {
			throw new UnsupportedOperationException();
		}
		
		@Override
		public ITypedRegion[] computePartitioning(final int offset, final int length) {
			return remap(this.masterPartitioner.computePartitioning(
					AbstractFragmentDocument.this.offsetInMaster + offset, length));
		}
		
		@Override
		public String getContentType(final int offset) {
			return this.masterPartitioner.getContentType(AbstractFragmentDocument.this.offsetInMaster + offset);
		}
		
		@Override
		public String[] getLegalContentTypes() {
			return this.masterPartitioner.getLegalContentTypes();
		}
		
		@Override
		public ITypedRegion getPartition(final int offset) {
			return remap(this.masterPartitioner.getPartition(AbstractFragmentDocument.this.offsetInMaster + offset));
		}
	}
	
	private class PartitionerMapper2 extends PartitionerMapper implements IDocumentPartitionerExtension2 {
		
		private final IDocumentPartitionerExtension2 masterPartitioner2;
		
		public PartitionerMapper2(final IDocumentPartitioner partitioner) {
			super(partitioner);
			this.masterPartitioner2= (IDocumentPartitionerExtension2) partitioner;
		}
		
		@Override
		public ITypedRegion[] computePartitioning(final int offset, final int length, final boolean includeZeroLengthPartitions) {
			return this.masterPartitioner2.computePartitioning(AbstractFragmentDocument.this.offsetInMaster + offset, length, includeZeroLengthPartitions);
		}
		
		@Override
		public String getContentType(final int offset, final boolean preferOpenPartitions) {
			return this.masterPartitioner2.getContentType(AbstractFragmentDocument.this.offsetInMaster + offset, preferOpenPartitions);
		}
		
		@Override
		public String @Nullable [] getManagingPositionCategories() {
			return this.masterPartitioner2.getManagingPositionCategories();
		}
		
		@Override
		public ITypedRegion getPartition(final int offset, final boolean preferOpenPartitions) {
			return this.masterPartitioner2.getPartition(AbstractFragmentDocument.this.offsetInMaster + offset, preferOpenPartitions);
		}
		
	}
	
	
	private final AbstractDocument master;
	
	private int offsetInMaster= 0;
	
	private byte change= NO_CHANGE;
	
	
	/**
	 * The default constructor does not perform any configuration but leaves it to the clients who
	 * must first initialize the implementation plug-ins and then call <code>completeInitialization</code>.
	 * Results in the construction of an empty document.
	 */
	public AbstractFragmentDocument() {
		super();
		
		this.master= createMasterDocument();
		
		this.master.addDocumentListener(new IDocumentListener() {
			@Override
			public void documentAboutToBeChanged(final DocumentEvent event) {
				switch (AbstractFragmentDocument.this.change) {
				case PREFIX_CHANGE:
					AbstractFragmentDocument.this.offsetInMaster+= - event.fLength + event.fText.length();
					return;
				case FRAGMENT_CHANGE:
					return;
				default:
					throw new UnsupportedOperationException();
				}
			}
			@Override
			public void documentChanged(final DocumentEvent event) {
			}
		});
		this.master.addDocumentPartitioningListener(new IDocumentPartitioningListener() {
			@Override
			@SuppressWarnings("deprecation")
			public void documentPartitioningChanged(final IDocument document) {
				fireDocumentPartitioningChanged(new Region(0, getLength()));
			}
		});
	}
	
	
	@Override
	protected void completeInitialization() {
		super.completeInitialization();
		
		addDocumentListener(new IDocumentListener() {
			@Override
			public void documentAboutToBeChanged(final DocumentEvent event) {
			}
			@Override
			public void documentChanged(final DocumentEvent event) {
				if (AbstractFragmentDocument.this.change != NO_CHANGE) {
					throw new IllegalStateException(String.valueOf(AbstractFragmentDocument.this.change));
				}
				
				AbstractFragmentDocument.this.change= FRAGMENT_CHANGE;
				try {
					replaceInMaster(AbstractFragmentDocument.this.offsetInMaster + event.fOffset,
							event.fLength, event.fText );
				}
				catch (final BadLocationException e) {
					ECommonsTextCorePlugin.log(new Status(IStatus.ERROR, ECommonsTextCorePlugin.BUNDLE_ID,
							"Failed to edit master document.", e ));
				}
				finally {
					AbstractFragmentDocument.this.change= NO_CHANGE;
				}
			}
		});
	}
	
	
	protected abstract AbstractDocument createMasterDocument();
	
	@Override
	public AbstractDocument getMasterDocument() {
		return this.master;
	}
	
	@Override
	public int getOffsetInMasterDocument() {
		return this.offsetInMaster;
	}
	
	@Override
	public TextRegion getRegionInMasterDocument() {
		synchronized (getLockObject()) {
			return JFaceTextRegion.newByStartLength(this.offsetInMaster, getLength());
		}
	}
	
	protected void replaceInMaster(final int offset, final int length, final String text)
			throws BadLocationException {
		this.master.replace(offset, length, text);
	}
	
	
	protected void setPrefix(final String text) {
		if (text == null) {
			throw new NullPointerException();
		}
		synchronized (getLockObject()) {
			if (this.change != NO_CHANGE) {
				throw new IllegalStateException(String.valueOf(this.change));
			}
			
			this.change= PREFIX_CHANGE;
			try {
				replaceInMaster(0, this.offsetInMaster, text);
				this.offsetInMaster= text.length();
			}
			catch (final BadLocationException e) {
				ECommonsTextCorePlugin.log(new Status(IStatus.ERROR, ECommonsTextCorePlugin.BUNDLE_ID,
						"Failed to edit master document.", e ));
			}
			finally {
				this.change= 0;
			}
		}
	}
	
	
	@Override
	public void setInitialLineDelimiter(final String lineDelimiter) {
		this.master.setInitialLineDelimiter(lineDelimiter);
		super.setInitialLineDelimiter(lineDelimiter);
	}
	
	
	@Override
	public void setDocumentPartitioner(final @Nullable IDocumentPartitioner partitioner) {
		this.master.setDocumentPartitioner(partitioner);
	}
	
	@Override
	public void setDocumentPartitioner(final String partitioning, final @Nullable IDocumentPartitioner partitioner) {
		this.master.setDocumentPartitioner(partitioning, partitioner);
	}
	
	@Override
	public String[] getPartitionings() {
		return this.master.getPartitionings();
	}
	
	@Override
	public @Nullable IDocumentPartitioner getDocumentPartitioner() {
		return getDocumentPartitioner(DEFAULT_PARTITIONING);
	}
	
	@Override
	public @Nullable IDocumentPartitioner getDocumentPartitioner(final String partitioning) {
		final IDocumentPartitioner masterPartitioner= this.master.getDocumentPartitioner(partitioning);
		if (masterPartitioner == null) {
			return null;
		}
		if (masterPartitioner instanceof IDocumentPartitionerExtension2) {
			return new PartitionerMapper2(masterPartitioner);
		}
		else {
			return new PartitionerMapper(masterPartitioner);
		}
	}
	
	@Override
	public String[] getLegalContentTypes() {
		return this.master.getLegalContentTypes();
	}
	
	@Override
	public String[] getLegalContentTypes(final String partitioning) throws BadPartitioningException {
		return this.master.getLegalContentTypes(partitioning);
	}
	
	@Override
	public ITypedRegion[] computePartitioning(final int offset, final int length) throws BadLocationException {
		return remap(this.master.computePartitioning(this.offsetInMaster + offset, length));
	}
	
	@Override
	public ITypedRegion[] computePartitioning(final String partitioning, final int offset, final int length,
			final boolean includeZeroLengthPartitions) throws BadLocationException, BadPartitioningException {
		return remap(this.master.computePartitioning(partitioning, this.offsetInMaster + offset, length, includeZeroLengthPartitions));
	}
	
	@Override
	public ITypedRegion getPartition(final int offset) throws BadLocationException {
		return remap(this.master.getPartition(this.offsetInMaster + offset));
	}
	
	@Override
	public ITypedRegion getPartition(final String partitioning, final int offset,
			final boolean preferOpenPartitions) throws BadLocationException, BadPartitioningException {
		return remap(this.master.getPartition(partitioning, this.offsetInMaster + offset, preferOpenPartitions));
	}
	
	@Override
	public String getContentType(final int offset) throws BadLocationException {
		return this.master.getContentType(this.offsetInMaster + offset);
	}
	
	@Override
	public String getContentType(final String partitioning, final int offset,
			final boolean preferOpenPartitions) throws BadLocationException, BadPartitioningException {
		return this.master.getContentType(partitioning, this.offsetInMaster + offset, preferOpenPartitions);
	}
	
	
	private ITypedRegion[] remap(final ITypedRegion[] masterRegions) {
		final ArrayList<ITypedRegion> regions= new ArrayList<>(masterRegions.length);
		for (final ITypedRegion masterRegion : masterRegions) {
			final ITypedRegion region= remap(masterRegion);
			if (region != null) {
				regions.add(region);
			}
		}
		return regions.toArray(new @NonNull ITypedRegion[regions.size()]);
	}
	
	private @Nullable ITypedRegion remap(final ITypedRegion masterRegion) {
		int offset= masterRegion.getOffset() - this.offsetInMaster;
		int length= masterRegion.getLength();
		if (offset + length >= 0) {
			if (offset < 0) {
				length= length + offset;
				offset= 0;
			}
//			System.out.println("partitiong mapping: ("+masterRegion.getOffset()+", "+masterRegion.getLength()+") -["+this.offsetInMaster+"]-> ("+offset+", "+length+")");
			return new TypedRegion(offset, length, masterRegion.getType());
		}
		
		{	final BadPartitioningException e= new BadPartitioningException("Failed to map partition from master to fragment document.");
			e.fillInStackTrace();
			ECommonsTextCorePlugin.log(new Status(IStatus.ERROR, ECommonsTextCorePlugin.BUNDLE_ID,
					"Failed to compute partition.", e ));
			return null;
		}
	}
	
}
