/*=============================================================================#
 # Copyright (c) 2015, 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.redocs.wikitext.r.ui.processing;

import java.lang.reflect.InvocationTargetException;
import java.util.regex.Matcher;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.osgi.util.NLS;

import org.eclipse.statet.jcommons.text.core.BasicTextRegion;
import org.eclipse.statet.jcommons.text.core.TextLineInformation;
import org.eclipse.statet.jcommons.text.core.TextRegion;

import org.eclipse.statet.docmlet.base.ui.DocmlBaseUI;
import org.eclipse.statet.docmlet.base.ui.processing.DocProcessingConfig;
import org.eclipse.statet.docmlet.wikitext.core.source.extdoc.YamlBlockWeaveParticipant;
import org.eclipse.statet.ltk.core.Ltk;
import org.eclipse.statet.ltk.core.SourceContent;
import org.eclipse.statet.ltk.model.core.LtkModels;
import org.eclipse.statet.ltk.model.core.element.SourceUnit;
import org.eclipse.statet.redocs.wikitext.r.core.WikitextRweaveCore;
import org.eclipse.statet.yaml.core.ast.Collection;
import org.eclipse.statet.yaml.core.ast.NodeType;
import org.eclipse.statet.yaml.core.ast.SourceComponent;
import org.eclipse.statet.yaml.core.ast.Tuple;
import org.eclipse.statet.yaml.core.ast.YamlAstNode;
import org.eclipse.statet.yaml.core.ast.YamlAstVisitor;
import org.eclipse.statet.yaml.core.ast.YamlParser;


public class YamlFormatDetector {
	
	
	private static final String FAIL= "<fail>"; //$NON-NLS-1$
	
	
	private final String modelTypeId;
	
	private Matcher extValidator;
	
	
	public YamlFormatDetector(final String modelTypeId) {
		this.modelTypeId= modelTypeId;
	}
	
	
	public String detect(final IFile file, final SubMonitor m) throws CoreException {
		m.beginTask(NLS.bind("Detecting output format of ''{0}''...", file.getName()),
				10 );
		
		final SourceUnit unit= LtkModels.getSourceUnitManager().getSourceUnit(this.modelTypeId,
				Ltk.PERSISTENCE_CONTEXT, file, true, m.newChild(1));
		try {
			final SourceContent content= unit.getContent(m.newChild(1));
			m.worked(0);
			final TextRegion yamlRegion= getYamlBlockRegion(content);
			m.worked(1);
			
			final YamlParser yamlParser= new YamlParser();
			yamlParser.setScalarText(true);
			
			final String code= content.getString(yamlRegion);
			final SourceComponent block= yamlParser.parse(code, null, yamlRegion.getStartOffset());
			
			final String format= searchOutputInfo(block, code);
			final String ext= toExtension(format);
			
			if (!isValidExt(ext)) {
				throw new CoreException(new Status(IStatus.ERROR, DocmlBaseUI.BUNDLE_ID,
						NLS.bind("Failed to detect file extension for format ''{0}''.",
								format )));
			}
			
			return ext;
		}
		catch (final Exception e) {
			throw new CoreException(new Status(IStatus.ERROR, WikitextRweaveCore.BUNDLE_ID, 0,
					NLS.bind("Failed to detect output format specified in doc (YAML) for ''{0}''.",
							file.getName() ),
					e ));
		}
		finally {
			unit.disconnect(m);
		}
	}
	
	
	private TextRegion getYamlBlockRegion(final SourceContent sourceContent)
			throws BadLocationException, CoreException {
		final TextLineInformation lines= sourceContent.getStringLines();
		final YamlBlockWeaveParticipant part= new YamlBlockWeaveParticipant();
		part.reset(sourceContent);
		
		int lineEndOffset= lines.getStartOffset(0);
		final int numLines= lines.getNumberOfLines();
		for (int line= 0; line < numLines; line++) {
			int lineOffset= lineEndOffset;
			lineEndOffset= lines.getEndOffset(line);
			if (part.checkStartLine(lineOffset, lineEndOffset)) {
				while (++line < numLines) {
					lineOffset= lineEndOffset;
					lineEndOffset= lines.getEndOffset(line);
					if (part.checkEndLine(lineOffset, lineEndOffset)) {
						return new BasicTextRegion(
								sourceContent.getStartOffset() + part.getStartOffset(),
								sourceContent.getStartOffset() + lineEndOffset );
					}
				}
			}
		}
		throw new CoreException(new Status(IStatus.ERROR, WikitextRweaveCore.BUNDLE_ID,
				"No YAML metadata block found." ));
	}
	
	
	private String searchOutputInfo(final SourceComponent block, final String code)
			throws CoreException, InvocationTargetException {
		
		class Searcher extends YamlAstVisitor {
			
			private String format;
			private String output;
			private String outputFormat;
			
			@Override
			public void visit(final Collection node) throws InvocationTargetException {
				if (node.getYamlParent().getNodeType() == NodeType.DOC_CONTENT
						&& node.getNodeType() == NodeType.MAP) {
					node.acceptInYamlChildren(this);
				}
			}
			
			@Override
			public void visit(final Tuple node) throws InvocationTargetException {
				if (node.getKeyNode().getNodeType() == NodeType.SCALAR) {
					final String key= node.getKeyNode().getText();
					if (key != null) {
						if (key.equals("format")) { //$NON-NLS-1$
							if (this.format == null) {
								if (node.getValueNode().getNodeType() == NodeType.SCALAR) {
									this.format= node.getValueNode().getText();
								}
								if (this.format == null) {
									this.format= FAIL;
								}
							}
						}
						else if (key.equals("output")) { //$NON-NLS-1$
							if (this.output == null) {
								switch (node.getValueNode().getNodeType()) {
								case SCALAR:
									this.output= node.getValueNode().getText();
									break;
								case MAP:
									if (node.getValueNode().hasChildren()) {
										final YamlAstNode firstOutput= node.getValueNode().getChild(0);
										if (firstOutput.getNodeType() == NodeType.MAP_ENTRY) {
											checkOutputEntry((Tuple) firstOutput);
										}
									}
									break;
								default:
									break;
								}
								if (this.output == null) {
									this.output= FAIL;
								}
							}
						}
					}
				}
			}
			
			private void checkOutputEntry(final Tuple outputEntry) {
				if (outputEntry.getKeyNode().getNodeType() == NodeType.SCALAR) {
					this.output= outputEntry.getKeyNode().getText();
				}
				if (outputEntry.getValueNode().getNodeType() == NodeType.MAP) {
					final Collection outputConfig= (Collection) outputEntry.getValueNode();
					for (int i= 0; i < outputConfig.getChildCount(); i++) {
						final YamlAstNode iChild= outputConfig.getChild(i);
						if (iChild.getNodeType() == NodeType.MAP_ENTRY) {
							final Tuple outputConfigEntry= (Tuple) iChild;
							if (outputConfigEntry.getKeyNode().getNodeType() == NodeType.SCALAR
									&& outputConfigEntry.getKeyNode().getText().equals("format") //$NON-NLS-1$
									&& outputConfigEntry.getValueNode().getNodeType() == NodeType.SCALAR) { 
								this.outputFormat= outputConfigEntry.getValueNode().getText();
							}
						}
					}
				}
			}
			
		}
		
		final Searcher searcher= new Searcher();
		block.acceptInYaml(searcher);
		
		if (searcher.format != null) {
			if (searcher.format == FAIL) {
				throw new CoreException(new Status(IStatus.ERROR, DocmlBaseUI.BUNDLE_ID,
						"Unexpected data for 'format'.\nYAML code:\n" + code ));
			}
			else {
				return searcher.format;
			}
		}
		else if (searcher.output != null) {
			if (searcher.outputFormat != null && isValidExt(toExtension(searcher.outputFormat))) {
				return searcher.outputFormat;
			}
			else if (searcher.output == FAIL) {
				throw new CoreException(new Status(IStatus.ERROR, DocmlBaseUI.BUNDLE_ID,
						"Unexpected data for 'output'.\nYAML code:\n" + code ));
			}
			else {
				return searcher.output;
			}
		}
		else {
			throw new CoreException(new Status(IStatus.ERROR, DocmlBaseUI.BUNDLE_ID,
					"No 'format' or 'output' entry found.\nYAML code:\n" + code ));
		}
	}
	
	
	private String toExtension(String format) {
		int idx= format.lastIndexOf(':');
		if (idx >= 0) {
			format= format.substring(idx + 1);
		}
		idx= format.indexOf('_');
		if (idx >= 0) {
			format= format.substring(0, idx);
		}
		
		switch (format) {
		case "native":
			return "hs";
		case "plain":
			return "txt";
		case "markdown":
			return "md";
		case "mediawiki":
			return "mediawiki";
		case "textile":
			return "textile";
		case "asciidoc":
			return "asciidoc";
		case "html":
		case "html5":
			return "html";
		case "pdf":
		case "latex":
		case "beamer":
			return "pdf";
		case "context":
			return "tex";
		case "texinfo":
			return "texi";
		case "docbook":
			return "dbk";
		case "opendocument":
		case "odt":
			return "odt";
		case "word":
		case "docx":
			return "docx";
		case "rtf":
			return "rtf";
		case "epub":
		case "epub3":
			return "epub";
		case "slidy":
		case "slideous":
		case "dzslides":
		case "revealjs":
		case "s5":
			return "html";
		default:
			return format;
		}
	}
	
	private boolean isValidExt(final String ext) {
		if (this.extValidator == null) {
			this.extValidator= DocProcessingConfig.VALID_EXT_PATTERN.matcher(ext);
		}
		else {
			this.extValidator.reset(ext);
		}
		return this.extValidator.matches();
	}
	
}
