/*=============================================================================#
 # Copyright (c) 2009, 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.yaml.ui.text;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.ITokenScanner;
import org.eclipse.jface.text.rules.Token;

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

import org.eclipse.statet.ecommons.text.core.input.DocumentParserInput;
import org.eclipse.statet.ecommons.text.ui.presentation.TextStyleManager;
import org.eclipse.statet.ecommons.text.ui.presentation.TextStyleManager.TextStyleToken;


@NonNullByDefault
public class YamlDefaultTextStyleScanner extends DocumentParserInput implements ITokenScanner {
	
	
	private static final byte ST_EOF= 0;
	private static final byte ST_DOCUMENT_SEPARATOR= 1;
	private static final byte ST_OTHER_INDICATOR= 2;
	private static final byte ST_BRACKET_INDICATOR= 3;
	
	private static final byte LAST_OTHER= 0;
	private static final byte LAST_EOF= 1;
	private static final byte LAST_EOL= 2;
	
	
	private final TextStyleManager<?> textStyles;
	private final @NonNull IToken[] tokens;
	private final TextStyleToken<?> defaultToken;
	
	private int currentOffset;
	private int currentLength;
	
	private byte nextType;
	private int nextLength;
	
	private byte lastChar;
	
	
	public YamlDefaultTextStyleScanner(final TextStyleManager<?> textStyles) {
		this.textStyles= textStyles;
		
		this.defaultToken= getToken(YamlTextStyles.TS_DEFAULT);
		this.tokens= new @NonNull IToken[4];
		this.tokens[ST_EOF]= Token.EOF;
		this.tokens[ST_DOCUMENT_SEPARATOR]= getToken(YamlTextStyles.TS_DOCUMENT_SEPARATOR);
		this.tokens[ST_OTHER_INDICATOR]= getToken(YamlTextStyles.TS_INDICATOR);
		this.tokens[ST_BRACKET_INDICATOR]= getToken(YamlTextStyles.TS_BRACKET);
	}
	
	
	protected TextStyleToken<?> getToken(final String key) {
		return this.textStyles.getToken(key);
	}
	
	
	@Override
	public void setRange(final IDocument document, final int offset, final int length) {
		reset(document);
		init(offset, offset + length);
		
		this.currentOffset= offset;
		this.currentLength= 0;
		this.nextLength= -1;
		
		try {
			if (offset > 0) {
				switch (document.getChar(offset - 1)) {
				case '\r':
				case '\n':
					this.lastChar= LAST_EOL;
					break;
				default:
					this.lastChar= LAST_OTHER;
				}
			}
			else {
				this.lastChar= LAST_EOL;
			}
		}
		catch (final BadLocationException e) {
			throw new RuntimeException(e);
		}
	}
	
	@Override
	public IToken nextToken() {
		this.currentOffset += this.currentLength;
		this.currentLength= this.nextLength;
		if (this.currentLength >= 0) {
			this.nextLength= -1;
			return this.tokens[this.nextType];
		}
		readNext();
		if (this.currentLength > 0) {
			return this.defaultToken;
		}
		else {
			this.currentLength= this.nextLength;
			this.nextLength= -1;
			return this.tokens[this.nextType];
		}
	}
	
	@Override
	public int getTokenOffset() {
		return this.currentOffset;
	}
	
	@Override
	public int getTokenLength() {
		return this.currentLength;
	}
	
	
	private void readNext() {
		int offset= 0;
		boolean nl= (this.lastChar == LAST_EOL);
		for (; true; offset++) {
			final int c= get(offset);
			switch (c) {
			case EOF:
				newToken(offset, ST_EOF, 0);
				this.lastChar= LAST_EOF;
				return;
			case '\n':
			case '\r':
				nl= true;
				continue;
			case '-':
				if (nl) {
					if (matches(1, '-', '-')) {
						newToken(offset, ST_DOCUMENT_SEPARATOR, 3);
						this.lastChar= LAST_OTHER;
						return;
					}
				}
				newToken(offset, ST_OTHER_INDICATOR, 1);
				this.lastChar= LAST_OTHER;
				return;
			case '?':
			case ':':
				newToken(offset, ST_OTHER_INDICATOR, 1);
				this.lastChar= LAST_OTHER;
				return;
			case '.':
				if (nl) {
					if (matches(1, '.', '.')) {
						int length= 3;
						while (get(length) == '.') {
							length++;
						}
						newToken(offset, ST_DOCUMENT_SEPARATOR, length);
						this.lastChar= LAST_OTHER;
						return;
					}
					nl= false;
				}
				continue;
			case '[':
			case ']':
			case '{':
			case '}':
				newToken(offset, ST_BRACKET_INDICATOR, 1);
				this.lastChar= LAST_OTHER;
				return;
//			case '&':
//			case '*':
//				TODO anchor
			default:
				nl= false;
				continue;
			}
		}
	}
	
	private void newToken(final int offset, final byte type, final int length) {
		this.currentLength= getLengthInSource(offset);
		consume(offset);
		
		this.nextType= type;
		this.nextLength= getLengthInSource(length);
		consume(length);
	}
	
}
