/*=============================================================================#
 # 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.internal.r.core.builder;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;

import org.eclipse.statet.jcommons.collections.IntArrayList;
import org.eclipse.statet.jcommons.collections.IntList;
import org.eclipse.statet.jcommons.text.core.TextLineInformation;
import org.eclipse.statet.jcommons.text.core.TextRegion;

import org.eclipse.statet.ecommons.text.core.JFaceTextRegion;


public class RdParser {
	
	public class LineInformation implements TextLineInformation {
		
		
		private final IntList offsets;
		
		
		public LineInformation() {
			this.offsets= new IntArrayList();
		}
		
		public void addLine(final int offset) {
			this.offsets.add(offset);
		}
		
		@Override
		public int getNumberOfLines() {
			return this.offsets.size();
		}
		
		@Override
		public int getLineOfOffset(final int offset) {
			if (this.offsets.size() == 0) {
				return -1;
			}
			int low= 0;
			int high= this.offsets.size() - 1;
			
			while (low <= high) {
				final int mid= (low + high) >> 1;
				final int lineOffset= this.offsets.getAt(mid);
				
				if (lineOffset < offset) {
					low= mid + 1;
				}
				else if (lineOffset > offset) {
					high= mid - 1;
				}
				else {
					return mid;
				}
			}
			return low - 1;
		}
		
		@Override
		public int getStartOffset(final int line) {
			if (line < 0 || line >= this.offsets.size()) {
				return -1;
			}
			return this.offsets.getAt(line);
		}
		
		@Override
		public int getEndOffset(final int line) {
			return (line + 1 == this.offsets.size()) ? RdParser.this.content.length : this.offsets.getAt(line + 1);
		}
		
		@Override
		public int getLength(final int line) {
			return (line + 1 == this.offsets.size()) ?
					(RdParser.this.content.length - this.offsets.getAt(line)) :
					(this.offsets.getAt(line + 1) - this.offsets.getAt(line) );
		}
		
		@Override
		public TextRegion getRegion(final int line) {
			return JFaceTextRegion.newByStartEnd(this.offsets.getAt(line),
					(line + 1 == this.offsets.size()) ?
							RdParser.this.content.length :
							this.offsets.getAt(line + 1) );
		}
		
	}
	
	
	private static final char[][] PLATFORM_KEYWORDS= {			// without '#'
		"ifdef".toCharArray(), "ifndef".toCharArray(), "endif".toCharArray() }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	
	private enum Last { NONE, NEWLINE, BACKSLASH }
	
	private final RTaskMarkerHandler markers;
	private final char[] content;
	
	private int currentOffset= 0;
	private final int currentLine= 1;
	private Last lastChar= Last.NONE;
	private final LineInformation lineStructure;
	
	
	public RdParser(final char[] content, final RTaskMarkerHandler markers) {
		this.content= content;
		this.markers= markers;
		this.lineStructure= new LineInformation();
	}
	
	public void check() throws CoreException {
		READ: for (; this.currentOffset < this.content.length; this.currentOffset++) {
				
			if (checkNewLine()) {
				continue READ;
			}
			
			if (checkBackslash()) {
				continue READ;
			}
					
			final char current= this.content[this.currentOffset];
			switch (current) {
			case '%':
				readComment();
				continue READ;
			
			case '#':
				if (this.lastChar == Last.NEWLINE) {
					CHECK_KEYS: for (int i= 0; i < PLATFORM_KEYWORDS.length; i++) {
						int offset= this.currentOffset + 1;
						CHECK_KEYCHARS: for (int j= 0; j < PLATFORM_KEYWORDS[i].length; j++) {
							if (offset < this.content.length && PLATFORM_KEYWORDS[i][j] == this.content[offset++]) {
								continue CHECK_KEYCHARS;
							}
							continue CHECK_KEYS;
						}
						readPlatformInstruction(PLATFORM_KEYWORDS[i]);
					}
				}
				continue READ;
			}
		}
	}
	
	private void readPlatformInstruction(final char[] keyword) {
		final int start= this.currentOffset;
		int end= this.currentOffset;
		
		READ: for (this.currentOffset++; this.currentOffset < this.content.length; this.currentOffset++) {
			
			end= this.currentOffset;
			if (checkNewLine()) {
				break READ;
			}
		}
	}
	
	private void readComment() throws CoreException {
		final int start= this.currentOffset;
		int end= this.currentOffset;
		
		READ: for (this.currentOffset++; this.currentOffset < this.content.length; this.currentOffset++) {
			end= this.currentOffset;
			if (checkNewLine()) {
				end--;
				break READ;
			}
		}
		try {
			this.markers.checkForTasks(new String(this.content, start, end - start + 1), start, this.lineStructure);
		}
		catch (final BadLocationException e) {
		}
	}
	
	private boolean checkNewLine() {
		final char current= this.content[this.currentOffset];
		if (current == '\r' || current == '\n') {
			
			if (current == '\r' && this.currentOffset + 1 < this.content.length
					&& this.content[this.currentOffset + 1] == '\n' ) {
				this.currentOffset++;
			}
			
			this.lineStructure.addLine(this.currentOffset);
			this.lastChar= Last.NEWLINE;
			return true;
		}
		return false;
	}
	
	private boolean checkBackslash() {
		if (this.content[this.currentOffset] == '\\') {
			this.lastChar= Last.BACKSLASH;
			return true;
		}
		if (this.lastChar == Last.BACKSLASH) {
			this.lastChar= Last.NONE;
			return true;
		}
		return false;
	}
	
}
