/*=============================================================================#
 # Copyright (c) 2014, 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.redocs.r.core.source;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;

import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;

import org.eclipse.statet.ecommons.text.core.sections.DocContentSections;
import org.eclipse.statet.ecommons.text.core.treepartitioner.TreePartitionNode;
import org.eclipse.statet.ecommons.text.core.treepartitioner.TreePartitionUtils;

import org.eclipse.statet.r.core.source.IRDocumentConstants;


@NonNullByDefault
public class RweaveDocSectionTreePartImpl {
	
	
	private final DocContentSections sections;
	
	
	public RweaveDocSectionTreePartImpl(final DocContentSections sections) {
		this.sections= sections;
	}
	
	
	public DocContentSections getSections() {
		return this.sections;
	}
	
	public @Nullable TreePartitionNode getRChunkRegion(final IDocument document, final int offset)
			throws BadLocationException {
		return TreePartitionUtils.searchNode(document, this.sections.getPartitioning(), offset, false,
				RweaveDocumentConstants.RCHUNK_BASE_CONTENT_TYPE );
	}
	
	public List<TreePartitionNode> getRChunkRegions(final IDocument document,
			final int offset, final int length) throws BadLocationException {
		final List<TreePartitionNode> nodes= new ArrayList<>();
		final TreePartitionNode root= TreePartitionUtils.getRootNode(document, this.sections.getPartitioning());
		
		addRChunkRegions(root, offset, offset + length, nodes);
		
		return nodes;
	}
	
	private void addRChunkRegions(final TreePartitionNode node, final int startOffset, final int endOffset,
			final List<TreePartitionNode> nodes) {
		final int childCount= node.getChildCount();
		int childIdx= 0;
		for (; childIdx < childCount; childIdx++) {
			final TreePartitionNode child= node.getChild(childIdx);
			if (child.getEndOffset() > startOffset) {
				break;
			}
		}
		for (; childIdx < childCount; childIdx++) {
			final TreePartitionNode child= node.getChild(childIdx);
			if (child.getStartOffset() >= endOffset) {
				break;
			}
			if (child.getType().getPartitionType() == RweaveDocumentConstants.RCHUNK_BASE_CONTENT_TYPE) {
				nodes.add(child);
			}
			else {
				addRChunkRegions(child, startOffset, endOffset, nodes);
			}
		}
	}
	
	public @Nullable IRegion getRChunkContentRegion(final IDocument document, final int offset)
			throws BadLocationException {
		final TreePartitionNode rChunk= getRChunkRegion(document, offset);
		if (rChunk == null || rChunk.getLength() <= 2) {
			return null;
		}
		final int beginLine= document.getLineOfOffset(rChunk.getStartOffset()) + 1;
		final int beginLineOffset= document.getLineOffset(beginLine);
		int endLine= document.getLineOfOffset(rChunk.getEndOffset());
		if (beginLine >= endLine) {
			return null;
		}
		int endLineOffset= document.getLineOffset(endLine);
		if (endLineOffset == rChunk.getEndOffset()) {
			endLine--;
			if (beginLine >= endLine) {
				return null;
			}
			endLineOffset= document.getLineOffset(endLine);
		}
		
		if (document.getChar(endLineOffset) == '@') { // closed
			return new Region(beginLineOffset, endLineOffset - beginLineOffset);
		}
		else { // node closed
			return new Region(beginLineOffset, rChunk.getEndOffset() - beginLineOffset);
		}
	}
	
	public List<TreePartitionNode> getRChunkCodeRegions(final IDocument document,
			final int offset, final int length) throws BadLocationException {
		final List<TreePartitionNode> rChunks= getRChunkRegions(document, offset, length);
		final List<TreePartitionNode> nodes= new ArrayList<>(rChunks.size());
		
		final int endOffset= offset + length;
		for (int i= 0; i < rChunks.size(); i++) {
			final TreePartitionNode node= rChunks.get(i);
			final int childCount= node.getChildCount();
			int childIdx= 0;
			for (; childIdx < childCount; childIdx++) {
				final TreePartitionNode child= node.getChild(childIdx);
				if (child.getEndOffset() > offset) {
					break;
				}
			}
			for (; childIdx < childCount; childIdx++) {
				final TreePartitionNode child= node.getChild(childIdx);
				if (child.getStartOffset() >= endOffset) {
					break;
				}
				if (child.getType().getPartitionType() == IRDocumentConstants.R_DEFAULT_CONTENT_TYPE) {
					nodes.add(child);
				}
			}
		}
		
		return nodes;
	}
	
	public @Nullable TreePartitionNode getRCodeRegion(final IDocument document, final int offset)
			throws BadLocationException {
		return TreePartitionUtils.searchNode(document, this.sections.getPartitioning(), offset, true,
				IRDocumentConstants.R_DEFAULT_CONTENT_TYPE );
	}
	
}
