

package org.sweble.wikitext.parser;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

import org.sweble.wikitext.parser.nodes.WtNode;
import org.sweble.wikitext.parser.nodes.WtParsedWikitextPage;
import org.sweble.wikitext.parser.parser.RatsWikitextParser;
import org.sweble.wikitext.parser.preprocessor.PreprocessedWikitext;

import xtc.parser.ParseError;
import xtc.parser.ParseException;
import xtc.parser.Result;
import xtc.parser.SemanticValue;
import de.fau.cs.osr.ptk.common.ParserCommon;

public class WikitextParser
		extends
			ParserCommon<WtNode>
{
	private final ParserConfig config;
	
	private RatsWikitextParser parser;
	
	// =========================================================================
	
	public WikitextParser(ParserConfig config)
	{
		this.config = config;
	}
	
	// =========================================================================
	
	@Override
	public Object getConfig()
	{
		return config;
	}
	
	// =========================================================================
	
	@Override
	public WtNode parseArticle(String src, String title) throws IOException, ParseException
	{
		PreprocessedWikitext ppWt =
				new PreprocessedWikitext(src, new WtEntityMapImpl());
		
		return parseArticle(ppWt, title);
	}
	
	public WtNode parseArticle(PreprocessedWikitext wikitext, String title) throws IOException, ParseException
	{
		Reader in = new StringReader(wikitext.getWikitext());
		
		int inputSize = wikitext.getWikitext().getBytes().length;
		
		parser = new RatsWikitextParser(in, title, inputSize);
		
		parser.getState().init(config, wikitext.getEntityMap());
		
		parser.setNodeFactory(config.getNodeFactory());
		
		Result r = null;
		
		//RatsWikitextParser.enableStats();
		{
			r = this.parser.pArticle(0);
		}
		if (RatsWikitextParser.isStatsEnabled())
			RatsWikitextParser.getStats().dump(System.err);
		
		if (r.hasValue())
		{
			SemanticValue v = (SemanticValue) r;
			
			if (v.value instanceof WtParsedWikitextPage)
			{
				return (WtNode) process((WtParsedWikitextPage) v.value);
			}
			else
			{
				throw new ParseException(
						"Internal parser error: Unexpected parser result type!");
			}
		}
		else
		{
			ParseError err = (ParseError) r;
			
			if (err.index == -1)
			{
				throw new ParseException(
						"Parse error: No information available");
			}
			else
			{
				throw new ParseException(String.format(
						"%s: %s",
						parser.location(err.index),
						err.msg));
			}
		}
	}
}
