/*=============================================================================#
 # 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.ltk.ast.core.util;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;

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

import org.eclipse.statet.ltk.ast.core.AstNode;
import org.eclipse.statet.ltk.ast.core.AstVisitor;


@NonNullByDefault
public class AstPrinter implements AstVisitor {
	
	
	protected final Writer writer;
	
	private @Nullable String text;
	
	private int level;
	
	private final int maxFragmentSize= 25;
	
	
	public AstPrinter(final Writer writer) {
		this.writer= writer;
	}
	
	
	public Writer getWriter() {
		return this.writer;
	}
	
	public void print(final AstNode node, final String text) throws IOException {
		try {
			this.level= 0;
			this.text= text;
			
			node.accept(this);
		}
		catch (final InvocationTargetException e) {
			throw (IOException) e.getCause();
		}
		finally {
			this.text= null;
		}
	}
	
	@Override
	public void visit(final AstNode node) throws InvocationTargetException {
		try {
			printIdent(this.level);
			this.writer.append('[');
			this.writer.append(Integer.toString(node.getStartOffset()));
			this.writer.append(", "); //$NON-NLS-1$
			this.writer.append(Integer.toString(node.getEndOffset()));
			this.writer.append(") "); //$NON-NLS-1$
			printNodeInfo(node);
			printFragment(node.getStartOffset(), node.getEndOffset());
			this.writer.append('\n');
			
			this.level++;
			node.acceptInChildren(this);
			this.level--;
		}
		catch (final IOException e) {
			throw new InvocationTargetException(e);
		}
	}
	
	protected void printIdent(final int depth) throws IOException {
		for (int i= 0; i < depth; i++) {
			this.writer.write("    "); //$NON-NLS-1$
		}
	}
	
	protected void printNodeInfo(final AstNode node) throws IOException {
		this.writer.append(node.getClass().getSimpleName());
	}
	
	protected void printFragment(final int startOffset, final int endOffset) throws IOException {
		final String text= this.text;
		if (text != null && this.maxFragmentSize > 0) {
			this.writer.write(": "); //$NON-NLS-1$
			int l= endOffset - startOffset;
			if (l <= this.maxFragmentSize) {
				writeEncoded(text, startOffset, l);
			}
			else if (this.maxFragmentSize < 13) {
				writeEncoded(text, startOffset, this.maxFragmentSize - 3);
				this.writer.write(" ... "); //$NON-NLS-1$
			}
			else {
				l= (this.maxFragmentSize - 3) / 2;
				writeEncoded(text, startOffset, l);
				this.writer.write(" ... "); //$NON-NLS-1$
				writeEncoded(text, endOffset - l, l);
			}
		}
	}
	
	private void writeEncoded(final String s, final int begin, final int length) throws IOException {
		final int end= begin + length;
		for (int i= begin; i < end; i++) {
			if (i < 0) {
				this.writer.write("<E: out of bounds>");
				i= 0;
			}
			else if (i >= s.length()) {
				this.writer.write("<E: out of bounds>");
				return;
			}
			final int c= s.charAt(i);
			if (c < 0x10) {
				this.writer.write("<0x0"); //$NON-NLS-1$
				this.writer.write(Integer.toHexString(c));
				this.writer.write('>');
			}
			else if (c < 0x20) {
				this.writer.write("<0x"); //$NON-NLS-1$
				this.writer.write(Integer.toHexString(c));
				this.writer.write('>');
			}
			else {
				this.writer.write(c);
			}
		}
	}
	
}
