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

import static org.eclipse.statet.ecommons.text.core.treepartitioner.TreePartitionNode.END_UNCLOSED;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.rules.ICharacterScanner;

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

import org.eclipse.statet.ecommons.text.CharacterScannerReader;
import org.eclipse.statet.ecommons.text.core.rules.BufferedDocumentScanner;
import org.eclipse.statet.ecommons.text.core.treepartitioner.TreePartitionNode;
import org.eclipse.statet.ecommons.text.core.treepartitioner.TreePartitionNodeScan;
import org.eclipse.statet.ecommons.text.core.treepartitioner.TreePartitionNodeScanner;


/**
 * This scanner recognizes the comments, platform specif., verbatim-like section
 * (and other/usual Rd code).
 */
public class RPartitionNodeScanner implements TreePartitionNodeScanner {
	
	
	public static final @Nullable TreePartitionNode findRRootNode(@Nullable TreePartitionNode node) {
		TreePartitionNode rNode;
		while (true) {
			if (node == null) {
				return null;
			}
			if (node.getType() instanceof RPartitionNodeType) {
				rNode= node;
				break;
			}
			node= node.getParent();
		}
		TreePartitionNode parentNode;
		while ((parentNode= rNode.getParent()) != null
				&& parentNode.getType() instanceof RPartitionNodeType) {
			rNode= parentNode;
		}
		return rNode;
	}
	
	
	/**
	 * Enum of states of the scanner.
	 * Note: id is index in array of tokens
	 * 0-7 are reserved.
	 **/
	protected static final int S_DEFAULT= 0;
	protected static final int S_QUOTED_SYMBOL= 1;
	protected static final int S_INFIX_OPERATOR= 2;
	protected static final int S_STRING_S= 3;
	protected static final int S_STRING_D= 4;
	protected static final int S_COMMENT= 5;
	protected static final int S_ROXYGEN= 6;
	
	
	/** Enum of last significant characters read. */
	protected static final byte LAST_OTHER= 0;
	protected static final byte LAST_EOF= 1;
	protected static final byte LAST_NEWLINE= 2;
	
	
	private final boolean isRoxygenEnabled;
	
	protected final CharacterScannerReader reader= new CharacterScannerReader(
			new BufferedDocumentScanner(1024) );
	
	private TreePartitionNodeScan scan;
	
	private TreePartitionNode rootNode;
	
	/** The current node */
	private TreePartitionNode node;
	/** The current node type */
	private RPartitionNodeType type;
	/** The last significant characters read. */
	protected byte last;
	
	
	public RPartitionNodeScanner() {
		this.isRoxygenEnabled= true;
	}
	
	
	@Override
	public int getRestartOffset(final TreePartitionNode node, final IDocument document,
			final int offset) throws BadLocationException {
		return offset;
	}
	
	@Override
	public RPartitionNodeType getDefaultRootType() {
		return RPartitionNodeType.DEFAULT_ROOT;
	}
	
	@Override
	public void execute(final TreePartitionNodeScan scan) {
		this.scan= scan;
		
		this.rootNode= null;
		this.node= null;
		
		setRange(scan.getStartOffset(), scan.getEndOffset());
		init();
		assert (this.rootNode != null && this.node != null);
		
		process();
	}
	
	protected final TreePartitionNodeScan getScan() {
		return this.scan;
	}
	
	protected void setRange(final int startOffset, final int endOffset) {
		this.reader.setRange(getScan().getDocument(), startOffset, endOffset - startOffset);
		updateLast();
	}
	
	protected void init() {
		final TreePartitionNode beginNode= getScan().getBeginNode();
		if (beginNode.getType() instanceof RPartitionNodeType) {
			initNode(beginNode, (RPartitionNodeType) beginNode.getType());
		}
		else {
			this.node= beginNode;
			addNode(getDefaultRootType(), getScan().getStartOffset());
			this.rootNode= this.node;
		}
	}
	
	protected final TreePartitionNode getRootNode() {
		return this.rootNode;
	}
	
	
	private void updateLast() {
		if (this.reader.getOffset() > 0) {
			this.last= LAST_OTHER;
			try {
				final char c= getScan().getDocument().getChar(this.reader.getOffset() - 1);
				switch (c) {
				case '\r':
				case '\n':
					this.last= LAST_NEWLINE;
					break;
				default:
					break;
				}
			}
			catch (final BadLocationException e) {}
		}
		else {
			this.last= LAST_NEWLINE;
		}
	}
	
	
	protected final void initNode(final TreePartitionNode node, final RPartitionNodeType type) {
		if (this.node != null) {
			throw new IllegalStateException();
		}
		this.node= node;
		this.type= type;
		this.rootNode= findRRootNode(node);
	}
	
	protected final void addNode(final RPartitionNodeType type, final int offset) {
		this.node= this.scan.add(type, this.node, offset, 0);
		this.type= type;
	}
	
	protected final TreePartitionNode getNode() {
		return this.node;
	}
	
	protected final void exitNode(final int offset, final int flags) {
		this.scan.expand(this.node, offset, flags, true);
		this.node= this.node.getParent();
		this.type= (RPartitionNodeType) this.node.getType();
	}
	
	protected final void exitNode() {
		this.node= this.node.getParent();
		this.type= (RPartitionNodeType) this.node.getType();
	}
	
	protected final void exitNodesTo(final TreePartitionNode stopNode,
			final int offset, final int flags) {
		while (this.node != stopNode) {
			exitNode(offset, flags);
		}
	}
	
	
	private void process() {
		while (true) {
			switch (this.last) {
			case LAST_EOF:
				handleEOF(this.type);
				return;
			case LAST_NEWLINE:
				handleNewLine(this.type);
				break;
			default:
				break;
			}
			
			switch (this.type.getScannerState()) {
			case S_DEFAULT:
				processDefault();
				continue;
			case S_QUOTED_SYMBOL:
				processQuotedSymbol();
				continue;
			case S_INFIX_OPERATOR:
				processInfixOperator();
				continue;
			case S_STRING_S:
				processStringS();
				continue;
			case S_STRING_D:
				processStringD();
				continue;
			case S_COMMENT:
			case S_ROXYGEN:
				processComment();
				continue;
			default:
				processExt(this.type);
				continue;
			}
		}
	}
	
	protected void processDefault() {
		LOOP: while (true) {
			switch (this.reader.read()) {
			case ICharacterScanner.EOF:
				this.last= LAST_EOF;
				return;
			case '\r':
				this.reader.read('\n');
				this.last= LAST_NEWLINE;
				return;
			case '\n':
				this.last= LAST_NEWLINE;
				return;
			case '"':
				addNode(RPartitionNodeType.STRING_D, this.reader.getOffset() - 1);
				this.last= LAST_OTHER;
				return;
			case '\'':
				addNode(RPartitionNodeType.STRING_S, this.reader.getOffset() - 1);
				this.last= LAST_OTHER;
				return;
			case '`':
				addNode(RPartitionNodeType.QUOTED_SYMBOL, this.reader.getOffset() - 1);
				this.last= LAST_OTHER;
				return;
			case '#':
				if (this.isRoxygenEnabled && this.reader.read('\'')) {
					addNode(RPartitionNodeType.ROXYGEN, this.reader.getOffset() - 2);
					this.last= LAST_OTHER;
					return;
				}
				else {
					addNode(RPartitionNodeType.COMMENT, this.reader.getOffset() - 1);
					this.last= LAST_OTHER;
					return;
				}
			case '%':
				addNode(RPartitionNodeType.INFIX_OPERATOR, this.reader.getOffset() - 1);
				this.last= LAST_OTHER;
				return;
			default:
				continue LOOP;
			}
		}
	}
	
	protected void processInfixOperator() {
		LOOP: while (true) {
			switch (this.reader.read()) {
			case ICharacterScanner.EOF:
				exitNode(this.reader.getOffset(), END_UNCLOSED);
				this.last= LAST_EOF;
				return;
			case '\r':
				exitNode(this.reader.getOffset() - 1, END_UNCLOSED);
				this.reader.read('\n');
				this.last= LAST_NEWLINE;
				return;
			case '\n':
				exitNode(this.reader.getOffset() - 1, END_UNCLOSED);
				this.last= LAST_NEWLINE;
				return;
			case '%':
				exitNode(this.reader.getOffset(), 0);
				this.last= LAST_OTHER;
				return;
			default:
				continue LOOP;
			}
		}
	}
	
	private void processBackslash() {
		this.last= LAST_OTHER;
		switch (this.reader.read()) {
		case ICharacterScanner.EOF:
			return;
		case '\r':
		case '\n':
			this.reader.unread();
			return;
		default:
			return;
		}
	}
	
	protected void processQuotedSymbol() {
		LOOP: while (true) {
			switch (this.reader.read()) {
			case ICharacterScanner.EOF:
				exitNode(this.reader.getOffset(), END_UNCLOSED);
				this.last= LAST_EOF;
				return;
			case '\r':
				this.reader.read('\n');
				this.last= LAST_NEWLINE;
				return;
			case '\n':
				this.last= LAST_NEWLINE;
				return;
			case '\\':
				processBackslash();
				continue;
			case '`':
				exitNode(this.reader.getOffset(), 0);
				this.last= LAST_OTHER;
				return;
			default:
				continue LOOP;
			}
		}
	}
	
	protected void processStringD() {
		LOOP: while (true) {
			switch (this.reader.read()) {
			case ICharacterScanner.EOF:
				exitNode(this.reader.getOffset(), END_UNCLOSED);
				this.last= LAST_EOF;
				return;
			case '\r':
				this.reader.read('\n');
				this.last= LAST_NEWLINE;
				return;
			case '\n':
				this.last= LAST_NEWLINE;
				return;
			case '\\':
				processBackslash();
				continue;
			case '\"':
				exitNode(this.reader.getOffset(), 0);
				this.last= LAST_OTHER;
				return;
			default:
				continue LOOP;
			}
		}
	}
	
	protected void processStringS() {
		LOOP: while (true) {
			switch (this.reader.read()) {
			case ICharacterScanner.EOF:
				exitNode(this.reader.getOffset(), END_UNCLOSED);
				this.last= LAST_EOF;
				return;
			case '\r':
				this.reader.read('\n');
				this.last= LAST_NEWLINE;
				return;
			case '\n':
				this.last= LAST_NEWLINE;
				return;
			case '\\':
				processBackslash();
				continue;
			case '\'':
				exitNode(this.reader.getOffset(), 0);
				this.last= LAST_OTHER;
				return;
			default:
				continue LOOP;
			}
		}
	}
	
	protected void processComment() {
		LOOP: while (true) {
			switch (this.reader.read()) {
			case ICharacterScanner.EOF:
				exitNode(this.reader.getOffset(), 0);
				this.last= LAST_EOF;
				return;
			case '\r':
				exitNode(this.reader.getOffset() - 1, 0);
				this.reader.read('\n');
				this.last= LAST_NEWLINE;
				return;
			case '\n':
				exitNode(this.reader.getOffset() - 1, 0);
				this.last= LAST_NEWLINE;
				return;
			default:
				continue LOOP;
			}
		}
	}
	
	protected void processExt(final RPartitionNodeType type) {
		throw new IllegalStateException("state= " + type.getScannerState());
	}
	
	protected void handleNewLine(final RPartitionNodeType type) {
	}
	
	protected void handleEOF(final RPartitionNodeType type) {
		final TreePartitionNode rootNode= getRootNode();
		final int offset= this.reader.getOffset();
		exitNodesTo(rootNode, offset, END_UNCLOSED);
		this.scan.expand(rootNode, offset, END_UNCLOSED, true);
	}
	
}
