package jp.hasc.hasctool.ui.views.grapheditor;


import jp.hasc.hasctool.core.blockdiagram.model.BlockDiagram;
import jp.hasc.hasctool.ui.views.beanslist.IBeansListTarget;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.IDocument;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;


/**
 * hascxbdファイルのエディタ。
 * This widget has 2 pages:
 * <ul>
 * <li>page 0 contains a nested text editor.
 * <li>page 1 shows the Graph of page 0 
 * </ul>
 */
public class BlockDiagramEditor extends MultiPageEditorPart implements IResourceChangeListener, IBeansListTarget {

	/** The text editor used in page 0. */
	private TextEditor editor;

	
	/** The BlockDiagram used in page 1. */
	private BlockDiagramGraphWidget bdg;
//	private StyledText text;
	/**
	 * Creates a multi-page editor example.
	 */
	public BlockDiagramEditor() {
		super();
		ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
	}
	/**
	 * Creates page 0 of the multi-page editor,
	 * which contains a text editor.
	 */
	private void createPage0() {
		try {
			editor = new TextEditor();
			int index = addPage(editor, getEditorInput());
//			setPageText(index, editor.getTitle());
			setPageText(index, "HascXBD");
		} catch (PartInitException e) {
			ErrorDialog.openError(
				getSite().getShell(),
				"Error creating nested text editor",
				null,
				e.getStatus());
		}
	}
	/**
	 * Creates page 1 of the multi-page editor,
	 */
	private void createPage1() {

		Composite composite = new Composite(getContainer(), SWT.NONE);
		FillLayout layout = new FillLayout();
		composite.setLayout(layout);
		bdg = new BlockDiagramGraphWidget(this, composite,SWT.NONE);

		IWorkbenchPartSite iw = getSite();
	// to show the property  of Selection;
		iw.setSelectionProvider(bdg.getGraphView());
		
		int index = addPage(composite);
		setPageText(index, "GraphEdit");
	}
	/**
	 * Creates the pages of the multi-page editor.
	 */
	protected void createPages() {
		createPage0();
		createPage1();
		
	}
	/**
	 * The <code>MultiPageEditorPart</code> implementation of this 
	 * <code>IWorkbenchPart</code> method disposes all nested editors.
	 * Subclasses may extend.
	 */
	public void dispose() {
		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
		super.dispose();
	}
	/**
	 * Saves the multi-page editor's document.
	 */
	public void doSave(IProgressMonitor monitor) {
		getEditor(0).doSave(monitor);
	}
	/**
	 * Saves the multi-page editor's document as another file.
	 * Also updates the text for page 0's tab, and updates this multi-page editor's input
	 * to correspond to the nested editor's.
	 */
	public void doSaveAs() {
		IEditorPart editor = getEditor(0);
		editor.doSaveAs();
		setPageText(0, editor.getTitle());
		setInput(editor.getEditorInput());
		setPartName(editor.getTitle());
	}
	/* (non-Javadoc)
	 * Method declared on IEditorPart
	 */
	public void gotoMarker(IMarker marker) {
		setActivePage(0);
		IDE.gotoMarker(getEditor(0), marker);
	}
	/**
	 * The <code>MultiPageEditorExample</code> implementation of this method
	 * checks that the input is an instance of <code>IFileEditorInput</code>.
	 */
	public void init(IEditorSite site, IEditorInput editorInput)
		throws PartInitException {
		if (!(editorInput instanceof IFileEditorInput))
			throw new PartInitException("Invalid Input: Must be IFileEditorInput");
		super.init(site, editorInput);
// set Editor name as file name
		setPartName(editorInput.getName());
	
	}
	/* (non-Javadoc)
	 * Method declared on IEditorPart.
	 */
	public boolean isSaveAsAllowed() {
		return true;
	}
	/**
	 * Calculates the contents of page 2 when the it is activated.
	 */
	protected void pageChange(int newPageIndex) {
		super.pageChange(newPageIndex);
		if (newPageIndex == 1) {
			setGraph();
		}
	}
	
	public boolean isGraphPageActive() {
		return getActivePage()==1;
	}
	
	
	/**
	 * Closes all project files on project close.
	 */
	public void resourceChanged(final IResourceChangeEvent event){
		if(event.getType() == IResourceChangeEvent.PRE_CLOSE){
			Display.getDefault().asyncExec(new Runnable(){
				public void run(){
					IWorkbenchPage[] pages = getSite().getWorkbenchWindow().getPages();
					for (int i = 0; i<pages.length; i++){
						if(((FileEditorInput)editor.getEditorInput()).getFile().getProject().equals(event.getResource())){
							IEditorPart editorPart = pages[i].findEditor(editor.getEditorInput());
							pages[i].closeEditor(editorPart,true);
						}
					}
				}            
			});
		}
	}
	
	// got from BlockDiagramExecutor
	private XStream newXStream() {
			XStream xs = new XStream(new DomDriver());
			xs.autodetectAnnotations(true);
			xs.aliasPackage("model", BlockDiagram.class.getPackage().getName());
			return xs;
	}
	/**
	 * Graph in page 1.
	 */
	void setGraph() {
		String editorText =
		editor.getDocumentProvider().getDocument(editor.getEditorInput()).get();
	// parse
		XStream xs = newXStream();
	
		BlockDiagram bd = (BlockDiagram)xs.fromXML(editorText);
//		BlockDiagram bd = createSampleDiagram();			

		bdg.setBlockDiagram(bd);

	}
	
	public void updateText() {
		// rebuild xml
		XStream xs = newXStream();
		
		BlockDiagram bd = bdg.getBlockDiagram();
		String text=xs.toXML(bd);
		
		IDocument doc = editor.getDocumentProvider().getDocument(editor.getEditorInput());
		doc.set(text);
	}
	
	public BlockDiagramGraphWidget getBlockDiagramGraphWidget() {
		return bdg;
	}
	
	@Override
	public void addBeanBlock(String clsName) {
		getBlockDiagramGraphWidget().addBlock(clsName);
	}
	
/*	public static BlockDiagram createSampleDiagram() {
		BlockDiagram bd=new BlockDiagram();
		//
		BeanBlock reader=new BeanBlock();
		reader.setName("reader");
		reader.setRuntimeClassName(LineReaderSource.class.getName());
		reader.setProperty("fileName","test");
		//si.setViewPosition(new Point(100,200));
		bd.addBlock(reader);
		//
		BeanBlock writer=new BeanBlock();
		writer.setName("writer");
		writer.setRuntimeClassName(LineWriterSink.class.getName());
		writer.setProperty("fileName","out.csv");
		//so.setViewPosition(new Point(200,100));
		bd.addBlock(writer);
		//
		Connection c1 = new Connection(reader.getPortByName(PortReference.OUTPUT_PORT), writer.getPortByName(PortReference.INPUT_PORT));
		//c1.getViewIntermediatePoints().add(new Point(200,100));
		bd.addConnection(c1);
		//
		return bd;
	}
*/
}
