/* $Id: GSEditor.java 664 2013-02-14 12:09:43Z ohura $ */
package smart_gs.smleditor.swingui;

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Rectangle2D;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JToolBar;

import smart_gs.GSConstants;
import smart_gs.all_text_search.SearchAllDialogManager;
import smart_gs.current_text_search.SearchDialogManager;
import smart_gs.debugprint.Debugprint;
import smart_gs.drawing_tool.SpreadCanvas;
import smart_gs.drawing_tool.drawing_mode.Mode;
import smart_gs.drawing_tool.state.DefaultState;
import smart_gs.drawing_tool.view.RectangleView;
import smart_gs.drawing_tool.view.View;
import smart_gs.image_search.logical.SearchResult;
import smart_gs.logical.Preference;
import smart_gs.logical.Region;
import smart_gs.logical.Spread;
import smart_gs.logical.TextSegment;
import smart_gs.swingui.AbstractGSWindow;
import smart_gs.swingui.GSTabbedPaneManager;
import smart_gs.swingui.IDATNameInGSTabbedPaneManager;
import smart_gs.swingui.ToolBarPanel;
import smart_gs.swingui.WorkspaceTabbedPane;
import smart_gs.swingui.WorkspaceWindow;
import smart_gs.swingui.toolbar.GSEditorToolBar;
import smart_gs.swingui.toolbar.HistoryToolBar;
import smart_gs.swingui.toolbar.ImageToolBar;
import smart_gs.swingui.toolbar.MoveTreeToolBar;
import smart_gs.swingui.toolbar.UtilityToolBar;
import sml_editor.swingui.EditorTextPane;

import com.hexidec.ekit.GSHTMLEditorFoucsActionListner;
import com.hexidec.ekit.GSHTMLEditorSearchActionListner;


@SuppressWarnings("serial")
public class GSEditor extends AbstractGSWindow {

	public static final int COMPACT = 0;
	public static final int FULL = 1;
	private String url;
	protected int open = 0;
	protected AtomicLong id;
	private Mode mode;
	private GSTabbedPaneWindowAdapter gsTabbedPaneWindowAdapter;
	private JPanel imagePanel;
	private JTabbedPane leftPanel;
	private JSplitPane mainSplitPane;
	private JSplitPane splitPane = null;
	private JPanel textDocumentPanel;
	private JPanel allDocumentPanel;
	private ToolBarPanel toolbarpanel;
	private JLabel textDocumentStatusBar;
	private int type;
	private Spread spread;
	private SpreadCanvas canvas;
	private int fullEditorDisplayMode;
	
	public GSEditor(Spread spread,int type)  {
		super("Editor: " + spread.getName());
		this.spread = spread;
		this.type = type;
		this.url = spread.getURI();

		this.tabbedPane = this.createTabbedPane(spread);
		this.canvas = this.getSMLTabbedPane().getSpreadCanvas();
		this.canvas.setGSEditor(this);
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		this.setLayout(new BorderLayout());
		this.fullEditorDisplayMode = Preference.getWorkspaceWindowMode();
		
		this.imagePanel = new JPanel(new BorderLayout());
		this.textDocumentPanel = new JPanel(new BorderLayout());
		this.allDocumentPanel = new JPanel(new BorderLayout());
		
		if (this.type == FULL) {
			this.enableEvents(AWTEvent.WINDOW_EVENT_MASK);
			this.getContentPane().setLayout(new BorderLayout());
			this.textDocumentPanel.add(this.tabbedPane, BorderLayout.CENTER);
			this.add(textDocumentPanel);
		} else {
			this.allDocumentPanel.add(this.tabbedPane, BorderLayout.CENTER);
			this.add(allDocumentPanel);
		}
		
		this.toolbarpanel = new ToolBarPanel(this,false);
		System.out.println(spread.getLineDirection());
		this.toolbarpanel.setLineDirectionIcon(spread.getLineDirection());
		this.toolbarpanel.validate();
		this.toolbarpanel.repaint();
		this.toolbarpanel.getImageToolBar().enableIcons();
		this.add(toolbarpanel, BorderLayout.NORTH);
		
		if (this.type == COMPACT) {
			this.setSize(860,680);
		}
		else {
			this.setSize(1180,680);
		}
		
		if (this.type == FULL) {
			arrangeFullEditorWindowPanes(this.fullEditorDisplayMode);
		}
		
		updateGUI();
	
		id = GSTabbedPaneManager.getControlID();
		gsTabbedPaneWindowAdapter = new GSTabbedPaneWindowAdapter(this.url,String.valueOf(id),getSMLTabbedPane(),this);
		this.addWindowListener(gsTabbedPaneWindowAdapter);
		updateMoveToolBar();
	}
	
	// The tabes of tabbedPane are set here by WorkspaceTabbedPane and GSTabbedPane. 
	public void setSpread(Spread spread){
		this.spread = spread;
		WorkspaceWindow.getInstance().save();
		if (this.tabbedPane != null) this.tabbedPane.clear();
		if (this.type == FULL) {
			this.tabbedPane = new WorkspaceTabbedPane(this,spread);
		} else {
			this.tabbedPane = new GSTabbedPane(this,spread);
		}

		this.toolbarpanel.setLineDirectionIcon(spread.getLineDirection());
		this.toolbarpanel.validate();
		this.updateGUI(spread);
//		this.tabbedPane.resetAllCaret();
		updateMoveToolBar();
	}
	
	public void updateGUI() {
		Spread spread = this.getSpread();
		if (spread != null)	this.updateGUI(spread);
	}
	
	public void updateMoveToolBar(){
		MoveTreeToolBar moveTreeToolBar = this.toolbarpanel.getMoveTreeToolBar();
		if(this.tabbedPane.getSpread() != null){
			moveTreeToolBar.setPathCount(this.tabbedPane.getSpread().getPageViewIndex());
		}
	}
	
	public void arrangeFullEditorWindowPanes(int fullEditorMode) {
		switch (fullEditorMode) 
		{
		case GSConstants.WINDOW_VERTICAL_IMAGE_TOP_MODE:
			mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
					this.imagePanel, this.textDocumentPanel);
			mainSplitPane.setDividerLocation(350);
			mainSplitPane.setOneTouchExpandable(true);
			if (splitPane != null) this.getContentPane().remove(splitPane);
			splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
					this.leftPanel, mainSplitPane);
			splitPane.setOneTouchExpandable(false);
			this.getContentPane().add(splitPane, BorderLayout.CENTER);
			this.setSize(1000, 780);
			break;
		case GSConstants.WINDOW_VERTICAL_IMAGE_BOTTOM_MODE:
			mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
					this.textDocumentPanel,this.imagePanel);
			mainSplitPane.setDividerLocation(350);
			mainSplitPane.setOneTouchExpandable(true);
			if (splitPane != null) this.getContentPane().remove(splitPane);
			splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
					this.leftPanel, mainSplitPane);
			splitPane.setOneTouchExpandable(false);
			this.getContentPane().add(splitPane, BorderLayout.CENTER);
			this.setSize(1000, 780);
			break;
		case GSConstants.WINDOW_HORIZONTAL_IMAGE_LEFT_MODE:
			mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
					this.imagePanel, this.textDocumentPanel);
			mainSplitPane.setDividerLocation(600);
			mainSplitPane.setOneTouchExpandable(true);
			mainSplitPane.getRightComponent().setMinimumSize(new Dimension(0,0));
			if (splitPane != null) this.getContentPane().remove(splitPane);
			splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
					this.leftPanel, mainSplitPane);
			splitPane.setOneTouchExpandable(false);
			this.getContentPane().add(splitPane, BorderLayout.CENTER);
			this.setSize(1200, 680);
			break;
		case GSConstants.WINDOW_HORIZONTAL_IMAGE_RIGHT_MODE:
			mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
					this.textDocumentPanel,this.imagePanel);
			mainSplitPane.setDividerLocation(600);
			mainSplitPane.setOneTouchExpandable(true);
			mainSplitPane.getLeftComponent().setMinimumSize(new Dimension(0,0));
			if (splitPane != null) this.getContentPane().remove(splitPane);
			splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
					this.leftPanel, mainSplitPane);
			splitPane.setOneTouchExpandable(false);
			this.getContentPane().add(splitPane, BorderLayout.CENTER);
			this.setSize(1200, 680);
			break;
		default:
			mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
					this.imagePanel, this.textDocumentPanel);
			break;
		}
		validate();
		repaint();
	}
	
	
	public static GSEditor createCompactGSEditor(Spread spread) {
		return new GSEditor(spread,COMPACT);
	}
	
	public static GSEditor createFullGSEditor(Spread spread) {
		return new GSEditor(spread,FULL);
	}

//	public static GSEditor createDefaultGSEditor(Spread spread) {
//		return new GSEditor(spread,Preference.getInstance().getEditorType());
//	}
	
	public GSEditor(Spread spread, Rectangle2D rect) {
		this(spread,GSEditor.COMPACT);
		View view = new RectangleView(rect);
		view.setIsEmphasized(true);
		Point point = new Point((int)rect.getX(),(int)rect.getY());
		this.tabbedPane.getSpreadCanvas().setCenterLocation(point);
		this.tabbedPane.getSpreadCanvas().addTempView(view);
		updateMoveToolBar();
	}
	
	public GSEditor(List<SearchResult> results) {
		this(results.get(0).getSpread(),GSEditor.COMPACT);
		for(int i=0;i<results.size();i++){
			Rectangle2D rect = results.get(i).getRectangle();
			View view = new RectangleView(rect);
			view.setIsEmphasized(true);
			this.tabbedPane.getSpreadCanvas().addTempView(view);
		}
		Point point = results.get(0).getRectangle().getLocation();
		this.tabbedPane.getSpreadCanvas().setCenterLocation(point);
		updateMoveToolBar();
	}
	public GSEditor(Region region) {
		this(region.getSpread(),GSEditor.COMPACT);
		View view = region.getView();
		view.setIsEmphasized(true);
		Rectangle2D rect = view.getRectangle2D();
		Point point = new Point((int)rect.getX(),(int)rect.getY());
		this.tabbedPane.getSpreadCanvas().setCenterLocation(point);
		this.tabbedPane.getSpreadCanvas().addTempView(view);
		updateMoveToolBar();
	}
	public GSEditor(TextSegment segment) {
		super("Editor");
	}

	public GSEditor(String string) {
		super("Editor:" + string);
	}

	public void setEditorTextPane(EditorTextPane textPane) {
		textPane.setSearchAction(new SearchAction(getGSEditorToolBar()));
		textPane.setFocusAction(new FoucsAction(this, getGSEditorToolBar()));
		this.tabbedPane.getGSEditorToolBar().setTextPane(textPane);
	}

	public void setEditorToolBar(JToolBar toolbar) {
		
	}
	public Spread getSpread() {
		return this.tabbedPane.getSpread();
	}
	
	public GSTabbedPane getSMLTabbedPane(){
		return this.tabbedPane;
	}

	@Override
	public void updateGUI(Spread spread) {
//		Pre is Full
		if (this.textDocumentPanel.getComponentCount() != 0) {
//			Post is Full
			if (this.type == FULL) {
				this.remove(this.allDocumentPanel);
				this.textDocumentPanel.removeAll();
				Component imageCanvas = tabbedPane.getTabbedPaneImageCanvas();
				this.imagePanel.removeAll();
				this.imagePanel.add(imageCanvas);
				this.textDocumentPanel.add(this.tabbedPane);
				textDocumentStatusBar = new JLabel("");
				JPanel jPanel = new JPanel(new BorderLayout());;
				jPanel.add(textDocumentStatusBar,BorderLayout.PAGE_START);
				this.textDocumentPanel.add(jPanel, BorderLayout.SOUTH);
				this.setFocusable(true);
			} 
//	       Post is Compact
			else {
				this.remove(this.textDocumentPanel);
				this.textDocumentPanel.removeAll();
				this.remove(this.imagePanel);
				this.remove(this.splitPane);
				this.tabbedPane.insertTab("Image",null,this.imagePanel.getComponent(0),"",0);
				this.tabbedPane.setSelectedIndex(0);
				this.imagePanel.removeAll();
				this.allDocumentPanel.removeAll();
				this.allDocumentPanel.add(this.tabbedPane);
				textDocumentStatusBar = new JLabel("");
				JPanel jPanel = new JPanel(new BorderLayout());;
				jPanel.add(textDocumentStatusBar,BorderLayout.PAGE_START);
				this.allDocumentPanel.add(jPanel, BorderLayout.SOUTH);
				this.add(allDocumentPanel);
			} 
		}
//		Pre is Compact
		else if (this.allDocumentPanel.getComponentCount() != 0) {
//			Post is Full
			if (this.type == FULL) {
				this.remove(this.allDocumentPanel);
				this.textDocumentPanel.removeAll();
				Component imagePanel = tabbedPane.getTabbedPaneImageCanvas();
				this.imagePanel.removeAll();
				this.imagePanel.add(imagePanel);
				this.textDocumentPanel.add(this.tabbedPane);
				textDocumentStatusBar = new JLabel("");
				JPanel jPanel = new JPanel(new BorderLayout());;
				jPanel.add(textDocumentStatusBar,BorderLayout.PAGE_START);
				this.textDocumentPanel.add(jPanel, BorderLayout.SOUTH);
				this.setFocusable(true);
			}
//		   Post is Compact
			else {
				this.allDocumentPanel.removeAll();
				this.allDocumentPanel.add(this.tabbedPane);
				textDocumentStatusBar = new JLabel("");
				JPanel jPanel = new JPanel(new BorderLayout());;
				jPanel.add(textDocumentStatusBar,BorderLayout.PAGE_START);
				this.allDocumentPanel.add(jPanel, BorderLayout.SOUTH);
			}
		}
		
		this.getUtilityToolBar().updateGSEditorTypeAndDisplayModeIcon();
		
		this.setTitle("Editor: " + spread.getName());
		this.validate();
		this.repaint();	
	}
	
	@Override
	public SpreadCanvas getSpreadCanvas() {
		return this.tabbedPane.canvas;
	}
	public Frame getFrame() {
		return this;
	}
	@Override
	public GSTabbedPane createTabbedPane(Spread spread) {
		return new GSTabbedPane(this, spread);
	}
	public void emphasize(String id) {
		this.tabbedPane.emphasize(id);
	}
	public void updateText() {
		this.tabbedPane.updateText();
	}

	public String getURL(){
		return url;
	}
	
	public AtomicLong getControlID(){
		return id;
	}
	public 	GSEditorToolBar getGSEditorToolBar(){
		return this.tabbedPane.getGSEditorToolBar();
	}
	
	// 20080916 hashimoto.
	// 現在選択されているタブで、カーソルを与えられたインデックスに移動させるメソッド
	public void setCaret(int index){
		getSMLTabbedPane().setCaret(index);
	}

	public void updateWindowListener() {
		this.removeWindowListener(this.gsTabbedPaneWindowAdapter);
		id = GSTabbedPaneManager.getControlID();
		gsTabbedPaneWindowAdapter = new GSTabbedPaneWindowAdapter(this.url,String.valueOf(id),getSMLTabbedPane(),this);
		this.addWindowListener(gsTabbedPaneWindowAdapter);
	}

	class GSTabbedPaneWindowAdapter extends WindowAdapter{
		protected String key;
		protected String id;
		protected GSTabbedPane gsTabbedPane;
		private AbstractGSWindow parent;
		
		public GSTabbedPaneWindowAdapter(String key,String id,GSTabbedPane gsTabbedPane, AbstractGSWindow parent){
			this.key = key;
			this.id = id;
			this.gsTabbedPane = gsTabbedPane;
			this.parent = parent;
		}
		public void windowClosing(WindowEvent e) {
			IDATNameInGSTabbedPaneManager.unregistorGSEditorTabbedPane(gsTabbedPane);
		}
		public void windowActivated(WindowEvent e) {
			SearchDialogManager.setGSEditorToolBar(getGSEditorToolBar());
			GSTabbedPane newTabbedPane = GSTabbedPaneManager.getGSTabbedPane(key);

        	if(newTabbedPane != null){
        		String windowid = GSTabbedPaneManager.getWindowsID(key);
        		if(windowid == null){
        			return;
        		}
        		if(windowid.equals(key + id)){
        			return;
        		}
        		newTabbedPane.save();
	        	String fstidatSource = newTabbedPane.getFirstIDATSource();
	        	this.gsTabbedPane.updateFirstIDAT(fstidatSource);

	        	String sndidatSource = newTabbedPane.getSecondIDATSource();
	        	this.gsTabbedPane.updateSecondIDAT(sndidatSource);

	        	String thrdidatSource = newTabbedPane.getThirdIDATSource();
	        	this.gsTabbedPane.updateThirdIDAT(thrdidatSource);

	        	this.gsTabbedPane.updateText();
	        	this.gsTabbedPane.save();
	        	GSTabbedPaneManager.removeGSTabbedPane(key);
        	}
        	open = 1;

        	Mode mode = ((GSEditor) parent).getMode();
        	if(mode != null) {
        		DefaultState.getInstance().setMode(mode);
        	}
	   		getTabbedPane().getFirstIDAT().setCaretPosition(0);
	   		getTabbedPane().getSecondIDAT().setCaretPosition(0);
	   		getTabbedPane().getThirdIDAT().setCaretPosition(0);
        }

		public void windowDeactivated(WindowEvent e) {
        	this.gsTabbedPane.save();
        	GSTabbedPaneManager.setGSTabbedPane(key, key + id ,gsTabbedPane);
        }
		public void windowClosed(WindowEvent e) {
        	open = 2;
        	GSTabbedPaneManager.close(key + id);
        }
	}
	
	public int isOpened(){
		return open;
	}

	private class SearchAction implements GSHTMLEditorSearchActionListner{
		protected GSEditorToolBar gsEditorToolBar;
		public SearchAction(GSEditorToolBar gsEditorToolBar) {
			this.gsEditorToolBar = gsEditorToolBar;
		}
		public void actionPerformed() {
			SearchDialogManager.setGSEditorToolBar(gsEditorToolBar);
			SearchDialogManager.visible();
		}
	}

	private class FoucsAction implements GSHTMLEditorFoucsActionListner{
		protected GSEditorToolBar gsEditorToolBar;
		protected GSEditor gsEditor;
		public FoucsAction(GSEditor gsEditor,GSEditorToolBar gsEditorToolBar) {
			this.gsEditor = gsEditor; 
			this.gsEditorToolBar = gsEditorToolBar;
		}
		public void focusGained() {
			SearchAllDialogManager.setEditor(gsEditor, gsEditorToolBar);
			SearchDialogManager.setGSEditorToolBar(gsEditorToolBar);
		}
		public void focusLost() {
			
		}
	}
	
	public void setMode(Mode mode) {
		this.mode = mode;
	}
	
	public Mode getMode() {
		return this.mode;
	}

	public void setURL(String url) {
		this.url = url;
	}
	/**
	 * @return the tabbedPane
	 */
	public GSTabbedPane getTabbedPane() {
		return this.tabbedPane;
	}

	public void setTabbedPane(GSTabbedPane tabbedPane) {
		this.tabbedPane = tabbedPane;
	}

	public ImageToolBar getImageToolBar() {
		return this.toolbarpanel.getImageToolBar();
	}
	
	public UtilityToolBar getUtilityToolBar() {
		return this.toolbarpanel.getUtilityToolBar();
	}

	public int getEditorType() {
		return this.type;
	}
	
	public int getDisplayMode() {
		return this.fullEditorDisplayMode;
	}

	public void setEditorType(int type) {
		this.type = type;
		if (this.type == COMPACT) {
			this.setSize(860,680);
		}
		else {
			this.setSize(1180,680);
		}
		
		if (this.type == FULL) {
			arrangeFullEditorWindowPanes(this.fullEditorDisplayMode);
		}

		updateGUI();
	}

	public void stepDisplayMode() {
		if (this.type != FULL) return;
		this.fullEditorDisplayMode = (this.fullEditorDisplayMode + 1) % 4;
		arrangeFullEditorWindowPanes(this.fullEditorDisplayMode);
	}
}
