/* $Id: WorkspaceWindow.java 1109 2016-05-19 00:05:03Z minao $ */
package smart_gs.swingui;

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.event.WindowEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JToolBar;
import javax.swing.Timer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import jp.ac.nii.hcp.shared.model.HCPDocument;
import jp.ac.nii.hcp.shared.model.HCPProject;

import org.apache.commons.io.FileUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import smart_gs.GSConstants;
import smart_gs.current_text_search.SearchDialogManager;
import smart_gs.dictionary.DictionaryXML;
import smart_gs.drawing_tool.ImageLabel;
import smart_gs.drawing_tool.SpreadCanvas;
import smart_gs.drawing_tool.drawing_mode.DefaultDrawingMode;
import smart_gs.drawing_tool.drawing_mode.LineSegEditorSelectMode;
import smart_gs.drawing_tool.drawing_mode.Mode;
import smart_gs.drawing_tool.state.DefaultState;
import smart_gs.logical.UsersNoteTree;
import smart_gs.logical.Preference;
import smart_gs.logical.Spread;
import smart_gs.logical.SpreadSelectionListManager;
import smart_gs.logical.SpreadTree;
import smart_gs.menu.export.ExportDialog;
import smart_gs.reasoning_web.logical.GS_RWRepository;
import smart_gs.reasoning_web.swingui.RWGlobalViewPanel;
import smart_gs.reasoning_web.swingui.ReasoningWebFrame;
import smart_gs.smleditor.swingui.GSEditorFrame;
import smart_gs.smleditor.swingui.GSKeyEventPost;
import smart_gs.smleditor.swingui.GSTabbedPane;
import smart_gs.smleditor.swingui.LineSegEditor;
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.action.GSFileFilter;
import smart_gs.util.CanonicalPathString;
import smart_gs.util.GSLog;
import smart_gs.util.GsXMLSaver;
import smart_gs.util.LinkCounter;
import smart_gs.util.ProjectSaver;
import sml_editor.swingui.EditorTextPane;
import webdav.WebDavDownLoadEvent;
import webdav.WebDavListenerAction;
import webdav.WebDavProcessor;

import com.hexidec.ekit.GSHTMLEditorSearchActionListner;

@SuppressWarnings("serial")
public class WorkspaceWindow extends AbstractGSWindow implements GSEditorFrame,
		Serializable{


	private static WorkspaceWindow singleton = new WorkspaceWindow();

	private JPanel imagePanel;
	private JTabbedPane leftPanel;
	private SpreadTreePanel spreadTreePanel;
	private UsersNoteTreePanel usersNoteTreePanel;
	private JPanel textDocumentPanel;
	private WorkspaceWindowNorthPanel workspaceWindowNorthPanel;
	private JLabel textDocumentStatusBar;
	private JLabel textDocumentStatusBar2;
	private JSplitPane mainSplitPane;
	private JSplitPane splitPane = null;
	private LineSegEditor lsg_editor = null;
	private boolean lsg_editor_opened = false;

	private GSKeyEventPost gsKeyEventPost;
	
	// kazuhiro kobayashi 10/9
	private File currentFile;
	
	//2008/9/6 North Grid
	//?X?V?t???O
	private static boolean updated = false;
	// 2009/01/23
	// ????Z?[?u???
	// 0 = ???[?J??
	// 1 = WebDav
	private static int lastsave = 0;
	
	// 0 normal exit, 1 aborted by user 
	private static int preferenceLoadStatus;

	private static boolean opened = false;
	
	private WebDavDownLoadEvent webDavDownLoadEvent;

	private Mode mode = new DefaultDrawingMode();

	private static boolean makeBackupFile = true;
	
	private HCPProject currentProject;
	
	private static boolean restoring = false;
	
	public static WorkspaceWindow getInstance() {
		return singleton;
	}
	
	public int getPreferenceLoadStatus() {return preferenceLoadStatus;}

	public WorkspaceWindow() {
		super("SMART-GS");
		
		preferenceLoadStatus = Preference.getInstance().load();
		
		if (preferenceLoadStatus !=0) return;

		String imageFolderPath = Preference.getInstance().getImageFolderPathString();
		File imageFolder = new File(imageFolderPath);
		if(!imageFolder.exists()){
			imageFolder.mkdirs();
		} 
		File tempDir = new File(GSConstants.TEMP_PATH);
		tempDir.mkdirs();

		this.enableEvents(AWTEvent.WINDOW_EVENT_MASK);
		this.imagePanel = new JPanel(new BorderLayout());
		this.spreadTreePanel = new SpreadTreePanel();
		this.usersNoteTreePanel = new UsersNoteTreePanel();
		this.leftPanel = new JTabbedPane();
		this.leftPanel.addTab("Images", this.spreadTreePanel);
		this.leftPanel.addTab("Notes", this.usersNoteTreePanel);
		this.getContentPane().setLayout(new BorderLayout());
		this.workspaceWindowNorthPanel = new WorkspaceWindowNorthPanel(this);
		this.getContentPane().add(workspaceWindowNorthPanel, BorderLayout.NORTH);
		this.textDocumentPanel = new JPanel(new BorderLayout());
		this.tabbedPane = new GSTabbedPane();		
		
		displayWorksapceWindow(Preference.getWorkspaceWindowMode());
		
		if(!Preference.getInstance().getDefaultGsFilePathString().equals("")){
			File defaultGsFile = new File(Preference.getInstance().getDefaultGsFilePathString());
			this.restore(defaultGsFile);
			this.autosave(defaultGsFile);
		} else {
			DictionaryXML.getInstance().init();
		}
		
		KeyboardFocusManager m = KeyboardFocusManager.getCurrentKeyboardFocusManager();
		gsKeyEventPost = new GSKeyEventPost();
		m.addKeyEventPostProcessor(gsKeyEventPost);
		this.addWindowFocusListener(new WorkspaceWindowFocusListener());

	}

	public void displayWorksapceWindow(int workspaceWindowMode) {
		switch (workspaceWindowMode) 
		{
		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(true);
			this.getContentPane().add(splitPane, BorderLayout.CENTER);
			this.setSize(1100, 800);
			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(true);
			this.getContentPane().add(splitPane, BorderLayout.CENTER);
			this.setSize(1100, 800);
			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(true);
			this.getContentPane().add(splitPane, BorderLayout.CENTER);
			this.setSize(1400, 700);
			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(true);
			this.getContentPane().add(splitPane, BorderLayout.CENTER);
			this.setSize(1400, 700);
			break;
		default:
			mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
					this.imagePanel, this.textDocumentPanel);
			break;
		}
		validate();
		repaint();
	}

	public void save() {
		this.tabbedPane.save();
	}
	public void setSpread(Spread spread) {
		this.setSpread(spread,true);
		Spread currentSpread = this.getSpread();
		String spreadNameExt = "";
		if (currentSpread != null) {
			spreadNameExt = "   " + currentSpread.getName();
		}
		if (currentFile != null) {
			this.setTitle(currentFile.getName() + " - SMART-GS" + spreadNameExt);
		} else if (currentProject != null) {
			this.setTitle("HCP Project: " + currentProject.name + " - SMART-GS" + spreadNameExt);
		} else {
			this.setTitle("SMART-GS" + spreadNameExt);
		}
		ToolBarPanel tbpanel = this.workspaceWindowNorthPanel.getToolBarPanel();
		tbpanel.setLineDirectionIcon(spread.getLineDirection());
		tbpanel.validate();
		tbpanel.repaint();
	}
	
	public void setSpread(Spread spread,boolean history) {
		this.save();
		if(this.tabbedPane != null){
			this.tabbedPane.clear();
		}

		this.tabbedPane = new WorkspaceTabbedPane(this, spread);	
		this.initializeGUI(spread);
		
		if(history){
			HistoryToolBar historyToolBar = this.workspaceWindowNorthPanel.getHistoryToolBar();
			int scale = this.getSpreadCanvas().imageLabel.scale;
			historyToolBar.addHistory(spread, scale);
		}
		
		updateMoveToolBar();
		
		Spread currentSpread = this.getSpread();
		String spreadNameExt = "";
		if (currentSpread != null) {
			spreadNameExt = "   " + currentSpread.getName();
		}
		if (currentFile != null) {
			this.setTitle(currentFile.getName() + " - SMART-GS" + spreadNameExt);
		} else if (this.currentProject != null) {
			this.setTitle("HCP Project: " + currentProject.name + " - SMART-GS" + spreadNameExt);
		} else {
			this.setTitle("SMART-GS" + spreadNameExt);
		}
		
		ToolBarPanel tbpanel = this.workspaceWindowNorthPanel.getToolBarPanel();
		tbpanel.setLineDirectionIcon(spread.getLineDirection());
		tbpanel.validate();
	}
	
	public boolean setSpreadToMoveInSpreadTree (Spread spread) {
		boolean canceled = false;
		boolean lsg_editor_opened_tmp = this.lsg_editor_opened;
		Point lsg_editor_position_tmp = null;
		if (this.lsg_editor != null) {
			lsg_editor_position_tmp = this.lsg_editor.getLocation();
			this.lsg_editor.windowClosingOperation();
			if (this.lsg_editor != null) {
				canceled = this.lsg_editor.spreadChangingCancled();
				if (canceled) return true;
			}
		}
		if (lsg_editor_opened_tmp) {
			setLineSegEditor(new LineSegEditor(spread));
			this.lsg_editor.setLocation(lsg_editor_position_tmp);
		}
		setSpread(spread);
		return false;
	}
	
	public boolean setSpreadToMoveInSpreadTree(Spread spread,boolean history) {
		boolean canceled = false;
		boolean lsg_editor_opened_tmp = this.lsg_editor_opened;
		Point lsg_editor_position_tmp = null;
		if (this.lsg_editor != null) {
			lsg_editor_position_tmp = this.lsg_editor.getLocation();
			this.lsg_editor.windowClosingOperation();
			if (this.lsg_editor != null) {
				canceled = this.lsg_editor.spreadChangingCancled();
				if (canceled) return true;
			}
		}
		if (lsg_editor_opened_tmp) {
			setLineSegEditor(new LineSegEditor(spread));
			this.lsg_editor.setLocation(lsg_editor_position_tmp);
		}
		setSpread(spread,history);
		return false;
	}
	
	public void updateSpread(Spread spread){
		this.tabbedPane.load();
	}

	public void updateMoveToolBar(){
		MoveTreeToolBar moveTreeToolBar = this.workspaceWindowNorthPanel.getMoveTreeToolBar();
		if(this.tabbedPane.getSpread() != null){
			moveTreeToolBar.setPathCount(this.tabbedPane.getSpread().getPageViewIndex());
		}
	}
	
	public void setImageSearch(String q){
		spreadTreePanel.search(q);
	}
	
	public Spread getSpreadInTree(int row){
		return spreadTreePanel.getSpreadInTree(row);
	}

	public void close(){
		super.close();
		SpreadTree.getInstance().clear();
		UsersNoteTree.getInstance().clear();
		GS_RWRepository.getInstance().clear();
		SpreadSelectionListManager.getInstance().clearSpreadSlectionLists();
		DictionaryXML.getInstance().init();
		ReasoningWebFrame.getInstance().reload();
		
		this.spreadTreePanel.repaint();

		this.setTitle("SMART-GS");
		this.tabbedPane.removeAll();
		this.tabbedPane.repaint();
		this.validate();
	}
	public void initializeGUI(Spread spread) {
		this.textDocumentPanel.removeAll();
		SpreadCanvas canvas = ((WorkspaceTabbedPane) tabbedPane).getTabbedPaneImageCanvas();
		this.imagePanel.removeAll();
		this.imagePanel.add(canvas);
		canvas.setPosition(Preference.getInstance().getImagePosition());

		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.validate();
	}

	@Override
	public GSTabbedPane createTabbedPane(Spread spread) {
		return new WorkspaceTabbedPane(this, spread);
	}

	public SpreadCanvas getSpreadCanvas() {
		if(this.tabbedPane == null) {
			return null;
		} else {
			return this.tabbedPane.getSpreadCanvas();
		}
	}

	public void setEditorToolBar(JToolBar toolbar) {

	}

	public void setEditorTextPane(EditorTextPane textPane) {
		textPane.setSearchAction(new GSHTMLEditorSearchActionListner(){
			public void actionPerformed() {
				SearchDialogManager.setGSEditorToolBar(WorkspaceWindow.getInstance().getGSEditorToolBar());
				SearchDialogManager.visible();				
			}
		});
		this.tabbedPane.setEditorTextPane(textPane);
	}

	public 	GSEditorToolBar getGSEditorToolBar(){
		return this.tabbedPane.getGSEditorToolBar();
	}

	public Spread getSpread() {
		return this.tabbedPane.getSpread();
	}

	public Frame getFrame() {
		return this;
	}

	public void restore(File file) {
		// kazuhiro kobayashi 10/9
		setRestoring(true);
		this.currentProject = null;
		this.currentFile = file;
		if (file.exists()==false) {
			JOptionPane.showMessageDialog(this, file.getName() + " does not exist\n");
			setRestoring(false);
			return;
		}
		DocumentBuilder builder;
		Document document;
		try {
			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			if(file.getName().endsWith(".gs")) { // old .gs file
				document = builder.parse(file);
			} else {
				ZipFile gsxFile = new ZipFile(file);
				ZipEntry gsxSpread = gsxFile.getEntry("spread.xml");
				if (gsxSpread==null){
					JOptionPane.showMessageDialog(this, file.getName() + ": Invalid gsx file.");
					setRestoring(false);
					gsxFile.close();
					return;
				}
				document = builder.parse(gsxFile.getInputStream(gsxSpread));
				gsxFile.close();
			}
			Element rootElement = document.getDocumentElement();
			String counterValue = rootElement.getAttribute("counter");
			if(counterValue != null){
				try{
					LinkCounter.setID(Integer.parseInt(counterValue));
				}catch(NumberFormatException e){
					setRestoring(false);
				}
			}
			this.setTitle(currentFile.getName() + " - SMART-GS");

			ReasoningWebFrame.getInstance().initializeContentsAndFrame();
			Element spreadElement = (Element) rootElement.getElementsByTagName(
					"spreadTree").item(0);
			SpreadTree.getInstance().restore(spreadElement);
			// 20070926 shimizu wrote;
			// 2011.01.03 shayashi changed?@for upper-compatibility
			Element usersNoteElement = (Element) rootElement
					.getElementsByTagName("usersNoteTree").item(0);
			UsersNoteTree.getInstance().clear();
			UsersNoteTree.getInstance().restore(usersNoteElement);
			Element rwElement = (Element) rootElement.getElementsByTagName(
					"reasoning_web").item(0);
			GS_RWRepository.getInstance().clear();
			GS_RWRepository.getInstance().restore(rwElement);
			Element sslists = (Element) rootElement.getElementsByTagName(
					"spreadSelectionLists").item(0);
			if (sslists != null) SpreadSelectionListManager.getInstance().restore(sslists);
			//2009/04/22 North Grid
			if( GS_RWRepository.getInstance().getBackgroundFilePath() != null &&
					GS_RWRepository.getInstance().getBackgroundFilePath().length() > 0 ){
				RWGlobalViewPanel.getInstance().setBackground(new File(GS_RWRepository.getInstance().getBackgroundFilePath()));
			}
			setUpdated(false);
			DictionaryXML.getInstance().load(file);
			DictionaryXML.getInstance().write();
			DictionaryXML.getInstance().setWarning(false);
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			setRestoring(false);
		} catch (SAXException e) {
			e.printStackTrace();
			setRestoring(false);
		} catch (IOException e) {
			e.printStackTrace();
			setRestoring(false);
		}
		this.tabbedPane.clear();
		this.tabbedPane.validate();
		this.tabbedPane.repaint();
		this.validate();
		setRestoring(false);
	}

	//2009/01/23 North Grid
	public boolean saveAll() {
		return saveAll(null);
	}

	public boolean saveAll(File file) {
		this.tabbedPane.save();
		try {
			Document document = this.buildXMLDocument();

			if(file == null){
				file = this.currentFile;
				// 2007/10/7 kazuhiro kobayashi
				String currentDirectory = Preference.getInstance()
						.getGsFolderPathString();
				File directory = new File(currentDirectory);
				JFileChooser chooser = new JFileChooser(directory);
				// 2007/10/9 kazuhiro kobayahsi
				if (this.currentFile != null) {
					chooser.setSelectedFile(this.currentFile);
				}
				chooser.setFileFilter(new GSFileFilter());
				String selectedFileName = "";
				while (!selectedFileName.endsWith(".gsx")) {
					int input = chooser.showSaveDialog(WorkspaceWindow.getInstance());
					if (input == JFileChooser.CANCEL_OPTION) {
						return false;
					}
					file = chooser.getSelectedFile();
					selectedFileName = file.getName();
					if (!selectedFileName.endsWith(".gsx")) {
						JOptionPane.showMessageDialog(null, "File name must ends with .gsx");
						chooser.setSelectedFile(new File(selectedFileName + ".gsx"));
					}
				}
			}
			String path = CanonicalPathString.get(file);
			new GsXMLSaver(document, path).save();
			setUpdated(false);
			return true;
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			return false;
		}
	}
	
	public boolean saveXMLDocument(File file, Document document) {
		if(file == null){
			file = this.currentFile;
			String currentDirectory = Preference.getInstance()
					.getGsFolderPathString();
			File directory = new File(currentDirectory);
			JFileChooser chooser = new JFileChooser(directory);
			if (this.currentFile != null) {
				chooser.setSelectedFile(this.currentFile);
			}
			chooser.setFileFilter(new GSFileFilter());
			String selectedFileName = "";
			while (!selectedFileName.endsWith(".gsx")) {
				int input = chooser.showSaveDialog(WorkspaceWindow.getInstance());
				if (input == JFileChooser.CANCEL_OPTION) {
					return false;
				}
				file = chooser.getSelectedFile();
				selectedFileName = file.getName();
				if (!selectedFileName.endsWith(".gsx")) {
					JOptionPane.showMessageDialog(null, "File name must ends with .gsx");
					chooser.setSelectedFile(new File(selectedFileName + ".gsx"));
				}
			}
		}
		String path = CanonicalPathString.get(file);
		new GsXMLSaver(document, path).save();
				setUpdated(false);
		return true;		
	}


	public Document buildXMLDocument() throws ParserConfigurationException {
		Document document = DocumentBuilderFactory.newInstance()
			.newDocumentBuilder().newDocument();
		Element rootElement = document.createElement("rootElement");
		rootElement.setAttribute("counter", String.valueOf(LinkCounter.intValue()));
		document.appendChild(rootElement);
		SpreadTree.getInstance().save(document, rootElement);
		UsersNoteTree.getInstance().save(document, rootElement);
		GS_RWRepository.getInstance().save(document, rootElement);
		SpreadSelectionListManager.getInstance().save(document, rootElement);
		return document;
	}
	
	public boolean saveProject() {
		if (this.currentProject == null) return false;
		
		this.save();
		try {
			Document xmlDocument = this.buildXMLDocument();
			new ProjectSaver(this.currentProject, xmlDocument).save();
			JOptionPane.showMessageDialog(WorkspaceWindow.getInstance(), "Saved: " + this.currentProject.name);
			setUpdated(false);
			return true;
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

	public void autosave(File file) {
		int autoSaveInterval = 10; // minutes
		Timer timer;
		
		timer = new Timer(1000 * 60 * autoSaveInterval, new AutosaveAction(file));
		timer.start();
	}

	public void exit() {
		// 2007/10/23 kazuhiro kobayashi
		int input ;

		//2008/9/5 North Grid
		//?X?V????m?F?_?C?A???O??\??????d?g?????
		boolean notcofirm = false;
		if( isUpdated() ){
			String filename = null;
			if(lastsave == 0){
				if(this.currentFile != null){
					filename = this.currentFile.getName();
				}
			}else{
				WebDavDownLoadEvent webDavDownLoadEvent = this.getWebDavDownLoadEvent();
				if(webDavDownLoadEvent != null){
					filename = webDavDownLoadEvent.getDownloaname();
				}
			}
			input = JOptionPane.showConfirmDialog(this, 
					(filename == null ? 
							"Save the edited contents?" :
							"\""+ filename + "\"   Save this file?")
					);

			if (input == JOptionPane.OK_OPTION) {
				if(this.getLastsave() == 0){
					if( this.saveAll() == false ) return;
				}else{
					WebDavListenerAction webDavListenerAction = new WebDavListenerAction();
					webDavListenerAction.save();
				}
			} else if (input == JOptionPane.NO_OPTION) {

			} else if (input == JOptionPane.CANCEL_OPTION) {
				return;
			}
			//2008/9/5 North Grid
			//??????m?F?_?C?A???O??\??????????C??
			notcofirm = true;
		}
		if( notcofirm == false ){
			input = JOptionPane.showConfirmDialog(this, "Exit SMART-GS?");
			if (input != JOptionPane.OK_OPTION) {
				return;
			}
		}
		Preference.getInstance().save();
		//20081031 North Grid Removed
		//SpreadTree.getInstance().saveLine();
		this.tabbedPane.save();
		unlock();
		System.exit(0);
	}
	public void unlock(){
		WebDavDownLoadEvent oldWebDavDownLoadEvent = getWebDavDownLoadEvent();
		if(oldWebDavDownLoadEvent != null){
			String unlockpath = oldWebDavDownLoadEvent.getDownloadpath();
			String unlockname = oldWebDavDownLoadEvent.getDownloaname();
			String locktoken = oldWebDavDownLoadEvent.getLockToken();
			WebDavProcessor webDavProcessor = WebDavProcessor.getInstance();
			if(webDavProcessor == null){
            	JOptionPane.showMessageDialog(
						new JFrame() , "It failed in login WebDav." , "fatal" ,
						JOptionPane.ERROR_MESSAGE
					);
            	return;
			}
			try {
				webDavProcessor.unlock(unlockpath, unlockname, locktoken);
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
		File tempDir = new File(GSConstants.TEMP_PATH);
		tempDir.delete();
		setWebDavDownLoadEvent(null);
	}
	
	
	public void export() {
		if(this.tabbedPane.isAvailable()){
			this.tabbedPane.save();
		}
		String currentFileName = this.currentFile.getName();
		int index = currentFileName.lastIndexOf('.');
		JDialog frame = new ExportDialog(currentFileName.substring(0, index));	
		frame.setVisible(true);
	}

	@Override
	protected void processWindowEvent(WindowEvent e) {
		if (e.getID() == WindowEvent.WINDOW_CLOSING) {
			this.exit();
		}
	}
	public void tabbedPaneSave(){
		synchronized (tabbedPane) {
			this.tabbedPane.save();
		}
	}
	
	public boolean isAlt() {
		return gsKeyEventPost.isAlt();
	}
	public boolean isCtrl() {
		return gsKeyEventPost.isCtrl();
	}
	public boolean isShift() {
		return gsKeyEventPost.isShift();
	}
	public boolean onlyOneOfAltCtrlShiftIsPressed (){
		return isAlt() ^ isCtrl() ^ isShift();
	}
	public void setStatusBarSource(String statusmessage){
		if (!isTabbedPaneAvailable()){
			JOptionPane.showMessageDialog(null, "Source: " + statusmessage);
			textDocumentStatusBar = new JLabel();
		}
		textDocumentStatusBar.setForeground(Color.RED);
		textDocumentStatusBar.setText("Source: " + statusmessage);
	}
	public void setStatusBarTarget(String statusmessage){
		if (!isTabbedPaneAvailable()){
			JOptionPane.showMessageDialog(null, "Target: " + statusmessage);
			textDocumentStatusBar = new JLabel();
		}
		textDocumentStatusBar.setForeground(Color.RED);
		textDocumentStatusBar.setText("Target: " + statusmessage);
	}
	public void setStatusBar2(String statusmessage){
		textDocumentStatusBar2.setText(statusmessage);
	}
	
	public void resetStatusBar() {
		textDocumentStatusBar.setText("");
	}
	
	public boolean isTabbedPaneAvailable(){
		return this.tabbedPane.isAvailable();
	}
	public GSTabbedPane getTabbedPane(){
		return this.tabbedPane;
	}

	public void processEvent(AWTEvent e) {
		super.processEvent(e);
		// ?A?N?e?B?u??????
		if(e.getID() == WindowEvent.WINDOW_ACTIVATED){
			// ?????E?B???h?E????
			SearchDialogManager.setGSEditorToolBar(getGSEditorToolBar());
			if(this.tabbedPane != null){
				String key = tabbedPane.getURI();
				if(key == null){
					return;
				}
	        	GSTabbedPane newTabbedPane = GSTabbedPaneManager.getGSTabbedPane(key);
	        	if(newTabbedPane != null){
	        		String windowid = GSTabbedPaneManager.getWindowsID(key);
	        		if(windowid == null){
	        			return;
	        		}
	        		if(windowid.equals(key)){
	        			return;
	        		}
	        		newTabbedPane.save();
		        	String fstidatSource = newTabbedPane.getFirstIDATSource();
		        	this.tabbedPane.updateFirstIDAT(fstidatSource);

		        	String secondSource = newTabbedPane.getSecondIDATSource();
		        	this.tabbedPane.updateSecondIDAT(secondSource);

		        	String thirdidatSource = newTabbedPane.getThirdIDATSource();
		        	this.tabbedPane.updateThirdIDAT(thirdidatSource);

		        	
		        	this.tabbedPane.updateText();
		        	this.tabbedPane.save();
		        	GSTabbedPaneManager.removeGSTabbedPane(key);
	        	}
			}
			if(this.mode != null){
				DefaultState.getInstance().setMode(this.mode);
			}
		}else if(e.getID() == WindowEvent.WINDOW_DEACTIVATED){
			if(this.tabbedPane != null){
		       	this.tabbedPane.save();
		       	String key = tabbedPane.getURI();
	        	GSTabbedPaneManager.setGSTabbedPane(key,key,tabbedPane);
			}
		}else if(e.getID() == WindowEvent.WINDOW_CLOSED){
			if(this.tabbedPane != null){
				String key = tabbedPane.getURI();
				if(key == null){
					return;
				}			
				GSTabbedPaneManager.close(key);
			}
		}
	}

	public static boolean isFileOpened() {
		return opened;
	}

	public void setFileOpened(boolean opened) {
		WorkspaceWindow.opened = opened;
		WorkspaceWindow.makeBackupFile = true;
	}

	//2008/9/6 North Grid
	//?X?V?t???O
	public static boolean isUpdated() {
		return updated;
	}

	public static void setUpdated(boolean updated) {
		if (isRestoring()) {
			return;
		}
		WorkspaceWindow.updated = updated;
		WorkspaceWindow window = getInstance();
		String title = window.getTitle();
		if(WorkspaceWindow.isFileOpened()) {
			window.backup();
		}
//		if(updated){
//			WorkspaceWindow.getInstance().northPanel.getGSMenuBar().setEnabledSaveMenu(true);
//		}
		if (updated) {
			if (!title.startsWith("*")) {
				window.setTitle("*" + title);
				window.repaint();
			}
		} else {
			if (title.startsWith("*")) {
				window.setTitle(title.substring(1));
				window.repaint();
			}
		}
	}


	public File getCurrentFile() {
		return currentFile;
	}
	
	public void setCurrentFile(File file) {
		this.currentFile = file;
	}

	// 2009/01/23 North Grid
	public WebDavDownLoadEvent getWebDavDownLoadEvent() {
		return webDavDownLoadEvent;
	}

	public void setWebDavDownLoadEvent(WebDavDownLoadEvent webDavDownLoadEvent) {
		this.webDavDownLoadEvent = webDavDownLoadEvent;
	}

	public int getLastsave() {
		return lastsave;
	}
	public void setLastsave(int lastsave) {
		WorkspaceWindow.lastsave = lastsave;
		if(lastsave == 1){
			this.currentFile = null;
		}
	}

	public void backup() {
		
		//2011/05/24 kukita: to cope with the error which occurs
		//when Smart-GS tries to make a backup file while the currentFile is null
		if (this.currentFile == null) {
			return;
		}
		try {
			if(makeBackupFile) {
				String backupFileName = this.currentFile.getPath() + ".bak";
				FileUtils.copyFile(this.currentFile, new File(backupFileName));
				GSLog.getInstance().info(backupFileName);
				makeBackupFile = false;
			}

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public ImageToolBar getImageToolBar () {
		return this.workspaceWindowNorthPanel.getImageToolBar();
	}

	public HistoryToolBar getHistoryToolBar() {
		return this.workspaceWindowNorthPanel.getHistoryToolBar();
	}
	
	public void setMode(Mode mode) {
		this.mode = mode;
	}
	
	public Mode getMode() {
		return this.mode;
	}

	public void initializeGUI() {
		Spread spread = this.getSpread();
		if (spread != null)	this.initializeGUI(spread);
	}

	
	public void openNewProject(HCPProject gsProject) {
		if (updated) {
			this.save();
		}
		this.currentProject = gsProject;
		LinkCounter.setID(0);
		this.setTitle(gsProject.name + " - SMART-GS");
		ReasoningWebFrame.getInstance().initializeContentsAndFrame();
		SpreadTree.getInstance().clear();
		UsersNoteTree.getInstance().clear();
		GS_RWRepository.getInstance().clear();
//		SpreadSelectionListManager.getInstance().clear();
//		GlobalViewPanel.getInstance().clear();
		
		//TODO 2012/03/28 kukita
		//initialize a dictionary
//		DictionaryXML.getInstance().load(file);
//		try {
//			DictionaryXML.getInstance().write();
//		} catch (ParserConfigurationException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		DictionaryXML.getInstance().setWarning(false);
		this.tabbedPane.clear();
		this.tabbedPane.validate();
		this.tabbedPane.repaint();
		this.validate();
		this.save();
		this.currentProject = gsProject;
	}

	public void openProject(HCPProject project, String path) {
	}

	public HCPProject getCurrentProject() {
		return this.currentProject;
	}
	public void setCurrentProject(HCPProject project) {
		this.currentProject = project;
	}
	
//	public void restoreProjectFromAttachment(HCPProject project) {
//		String workspaceDir = Preference.getInstance().getWorkspaceDirectory();
//		String inputFileName = workspaceDir + File.separator + "repository" 
//							+ File.separator + project.name
//							+ File.separator + "attachment"
//							+ File.separator + project.name + ".gsx";		
//		File file = new File(inputFileName);
//		this.restore(file);
//		if (file != null) {
//			this.currentProject = project;
//		}
//	}

	public void restoreProject(HCPProject project) {
		setRestoring(true);
		this.saveAll();
		this.currentFile = null;
		HCPDocument doc = selectHCPDocument(project, "main");
		if (this.openHCPDocument(doc)) {
			this.currentProject = project;
			this.setTitle("HCP Project: " + project.name);
			JOptionPane.showMessageDialog(WorkspaceWindow.getInstance(), "Opened: " + project.name);
			WorkspaceWindow.getInstance().setVisible(true);
		} else {
			JOptionPane.showMessageDialog(WorkspaceWindow.getInstance(), "There is no main document in " + project.name);
		}
		setRestoring(false);
	}

	private boolean openHCPDocument(HCPDocument doc) {
		String path = Preference.getInstance().getWorkspaceDirectory() 
						+ File.pathSeparator + "xml"
						+ File.pathSeparator + doc.id
						+ File.pathSeparator;
		DocumentBuilder builder;
		Document document;
		try {
			File file = new File(path+"spread.xml");
			PrintWriter pw = new PrintWriter(
					new BufferedWriter(
							new OutputStreamWriter(
									new FileOutputStream(file),"UTF-8"
									)
							)
					);
			pw.write(doc.source);
			pw.close();
			
			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			document = builder.parse(file);
			Element rootElement = document.getDocumentElement();
			String counterValue = rootElement.getAttribute("counter");
			if(counterValue != null){
				try{
					LinkCounter.setID(Integer.parseInt(counterValue));
				}catch(NumberFormatException e){}
			}
			this.setTitle(doc.id + " - SMART-GS");

			ReasoningWebFrame.getInstance().initializeContentsAndFrame();
			Element spreadElement = (Element) rootElement.getElementsByTagName(
					"spreadTree").item(0);
			SpreadTree.getInstance().restore(spreadElement);
			Element usersNoteElement = (Element) rootElement
					.getElementsByTagName("usersNoteTree").item(0);
			UsersNoteTree.getInstance().clear();
			UsersNoteTree.getInstance().restore(usersNoteElement);
			Element rwElement = (Element) rootElement.getElementsByTagName(
					"reasoning_web").item(0);
			GS_RWRepository.getInstance().restore(rwElement);
			Element sslists = (Element) rootElement.getElementsByTagName(
					"spreadSelectionLists").item(0);
			if (sslists != null) SpreadSelectionListManager.getInstance().restore(sslists);
			if( GS_RWRepository.getInstance().getBackgroundFilePath() != null &&
					GS_RWRepository.getInstance().getBackgroundFilePath().length() > 0 ){
				RWGlobalViewPanel.getInstance().setBackground(new File(GS_RWRepository.getInstance().getBackgroundFilePath()));
			}
			setUpdated(false);
//			DictionaryXML.getInstance().load(file);
//			DictionaryXML.getInstance().write();
//			DictionaryXML.getInstance().setWarning(false);
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			new smart_gs.network.ShowResultDialog("Restore Project", e);
		} catch (SAXException e) {
			e.printStackTrace();
			new smart_gs.network.ShowResultDialog("Restore Project", e);
		} catch (IOException e) {
			e.printStackTrace();
			new smart_gs.network.ShowResultDialog("Restore Project", e);
		}
		this.tabbedPane.clear();
		this.tabbedPane.validate();
		this.tabbedPane.repaint();
		this.validate();
		return true;
	}

	private static HCPDocument selectHCPDocument(HCPProject project, String id) {
		List<HCPDocument> docs = project.documents;
		for (int i = 0; i < docs.size(); i++) {
			if (docs.get(i).id.equals(id)) {
				return docs.get(i);
			}
		}
		JOptionPane.showMessageDialog(WorkspaceWindow.getInstance(), "There is no main document in " + project.name);
		return null;
	}

	public GSKeyEventPost getKeyEventPost() {
		return this.gsKeyEventPost;
	}

	public boolean editingProject() {
		return this.currentProject != null;
	}

	public static boolean isRestoring() {
		return restoring;
	}

	public static void setRestoring(boolean r) {
		restoring = r;
	}
	
	public boolean isLineSegEditorOpen () {
		return this.lsg_editor != null;
	}
	public void setLineSegEditor(LineSegEditor editor) {
		if (editor != null) {
			this.lsg_editor = editor;
			this.lsg_editor_opened = true;
			lineSegEditorButtonEnable(false);
			this.lsg_editor.repaint();
		} else {
			this.lsg_editor = null;
			this.lsg_editor_opened = false;
			lineSegEditorButtonEnable(true);		
		}
	}
	public void initializeLineSegEditor() {
		this.lsg_editor_opened = false;
		this.lsg_editor = null;
		lineSegEditorButtonEnable(true);
	}
	
	public LineSegEditor getLineSegEditor() {
		return this.lsg_editor;
	}
	
	public void lineSegEditorButtonEnable(boolean b) {
		this.workspaceWindowNorthPanel.lineSegEditorButtonEnable(b);
	}

	public void updateAndPaintSpreadTree() {
		spreadTreePanel.updateAndPaintSpreadTree();
	}
	
}