package tk.eclipse.plugin.dtdeditor.editors;

import java.io.File;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;

import tk.eclipse.plugin.htmleditor.HTMLPlugin;
import tk.eclipse.plugin.htmleditor.HTMLProjectParams;
import tk.eclipse.plugin.htmleditor.editors.HTMLSourceEditor;
import tk.eclipse.plugin.htmleditor.editors.IHTMLOutlinePage;
import tk.eclipse.plugin.xmleditor.editors.SchemaGenerator;

import com.wutka.dtd.DTDParseException;
import com.wutka.dtd.DTDParser;

/**
 * DTD editor.
 * 
 * @author Naoki Takezoe
 */
public class DTDEditor extends HTMLSourceEditor {
	
	public static final String ACTION_GEN_XSD = "_generate_xsd";
	
	public DTDEditor(){
		super(new DTDConfiguration(HTMLPlugin.getDefault().getColorProvider()));
		setAction(ACTION_GEN_XSD,new GenerateXSDAction());
	}
	
	@Override
  public void createPartControl(Composite parent) {
		super.createPartControl(parent);
		getPairMatcher().setDelimiter('<');
	}
	
	@Override
  protected IDocumentProvider createDocumentProvider(IEditorInput input){
		if(input instanceof IFileEditorInput){
			return new DTDTextDocumentProvider();
		} else if(input instanceof IStorageEditorInput){
			return new DTDFileDocumentProvider();
		} else {
			return new DTDTextDocumentProvider();
		}
	}
	
	@Override
  protected IHTMLOutlinePage createOutlinePage() {
		return new DTDOutlinePage(this);
	}
	
	@Override
  protected void addContextMenuActions(IMenuManager menu){
		menu.add(new Separator(GROUP_HTML));
		addAction(menu,GROUP_HTML,ACTION_COMMENT);
		addAction(menu,GROUP_HTML,ACTION_GEN_XSD);
	}
	
	@Override
  protected void doValidate() {
		try {
			ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
				public void run(IProgressMonitor monitor) throws CoreException {
					IFileEditorInput input = (IFileEditorInput)getEditorInput();
					IFile file = input.getFile();
					
					file.deleteMarkers(IMarker.PROBLEM,false,0);
					
					try {
						HTMLProjectParams params = new HTMLProjectParams(file.getProject());
						if(!params.getValidateDTD()){
							return;
						}
						
						new DTDParser(new StringReader(getHTMLSource())).parse();
					} catch(DTDParseException ex){
						DTDErrorInfo error = new DTDErrorInfo(ex);
						IMarker marker = file.createMarker(IMarker.PROBLEM);
						Map<String, Object> map = new HashMap<String, Object>();
						map.put(IMarker.SEVERITY, Integer.valueOf(IMarker.SEVERITY_ERROR));
						map.put(IMarker.MESSAGE, error.getError());
						map.put(IMarker.LINE_NUMBER,Integer.valueOf(error.getLine()));
						marker.setAttributes(map);
					} catch(Exception ex){
						HTMLPlugin.logException(ex);
					}
				}
			},null);
		} catch(Exception ex){
			HTMLPlugin.logException(ex);
		}
	}
	
	private static class DTDErrorInfo {
		
		private Pattern pattern = Pattern.compile("At line ([0-9]+), column ([0-9]+): (.+)$");
		
		private int line;
		private int column;
		private String error;
		
		public DTDErrorInfo(DTDParseException ex){
			Matcher matcher = pattern.matcher(ex.toString());
			if(matcher.find()){
				line   = Integer.parseInt(matcher.group(1));
				column = Integer.parseInt(matcher.group(2));
				error  = matcher.group(3);
			}
		}
		
		public int getColumn() {
			return column;
		}

		public String getError() {
			return error;
		}

		public int getLine() {
			return line;
		}
	}
	
	/** The action to generate XML schema from DTD. */
	private class GenerateXSDAction extends Action {
		public GenerateXSDAction(){
			super(HTMLPlugin.getResourceString("XMLEditor.GenerateXSD"), 
					HTMLPlugin.getDefault().getImageRegistry().getDescriptor(HTMLPlugin.ICON_XSD));
		}
		@Override
    public void run() {
			FileDialog dialog = new FileDialog(getViewer().getTextWidget().getShell(),SWT.SAVE);
			dialog.setFilterExtensions(new String[]{"*.xsd"});
			String file = dialog.open();
			if(file!=null){
				try {
					SchemaGenerator.generateXSDFromDTD(getFile(),new File(file));
				} catch(Exception ex){
					HTMLPlugin.openAlertDialog(ex.toString());
				}
			}
		}
	}	
}
