/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * StaticModelUI.java
 *
 * Created on May 1, 2010, 9:00:48 PM
 */
package dowser.ui;

import dowser.Const;
import dowser.model.Attribute;
import dowser.model.DomainEntity;
import dowser.model.DomainModel;
import dowser.model.ModelParser;
import dowser.model.Operation;
import dowser.model.StaticModelValidator;
import dowser.model.StaticModelValidator.IModelChangeListener;
import dowser.model.TextRestrictor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.tree.TreePath;
import ontology.ui.OntologyUI;

/**
 *
 * @author chepa
 */
public class StaticModelUI extends javax.swing.JFrame implements IModelChangeListener {

	public boolean updateOperationName(DomainModel model, Operation operation, String newName) {
		return false;
	}

	public boolean updateAttributeName(DomainModel model, Attribute attribute, String newName) {
		return false;
		//throw new UnsupportedOperationException("Not supported yet.");
	}

	public boolean updateClassName(DomainModel model, dowser.model.Class cClass, String newName) {
		if (m_DomainModel != model) {
			return false;
		}
		String cName = cClass.getName();
		if (!cName.equals(newName)) {
			String newText = txtSpec.getText().replaceAll("[ ]" + cName + "[ ]", " " + newName + " ");
			newText = newText.replaceAll(cName + "[.]", newName + ".");
			newText = newText.replaceAll("[\n]" + cName, "[\n]" + newName);
			txtSpec.setText(newText);
			return true;
		}
		return false;
	}
	protected DomainTreeModel m_DomainTreeModel = new DomainTreeModel();
	protected DomainModel m_DomainModel = new DomainModel();
	protected DomainRenderer m_DomainRenderer = new DomainRenderer();

	/** Creates new form StaticModelUI */
	public StaticModelUI() {
		initComponents();
		StaticModelValidator.addListener(this);
		txtSpec.addKeyListener(new TextRestrictor() {

			@Override
			public void keyTyped(KeyEvent e) {
				if (e.getKeyChar() == '.') {
					return;
				}
				super.keyTyped(e);
			}
		});
		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowOpened(WindowEvent e) {
				setExtendedState(JFrame.MAXIMIZED_BOTH);
			}
		});
		trStaticModel.setSelectionModel(null);
		trStaticModel.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseClicked(MouseEvent e) {
				if (e.getClickCount() == 2) {
					processTrigger(e);
				}
			}

			@Override
			public void mousePressed(MouseEvent e) {
				trStaticModel.setEditable(false);
			}

			private void processTrigger(MouseEvent e) {
				TreePath path = trStaticModel.getClosestPathForLocation(e.getX(), e.getY());
				if (path == null) {
					return;
				}
				Object obj = path.getLastPathComponent();
				if (obj == null) {
					return;
				}
				if (!(obj instanceof DomainEntity)) {
					return;
				}
				trStaticModel.setEditable(true);
				trStaticModel.startEditingAtPath(path);
			}

			@Override
			public void mouseReleased(MouseEvent e) {
				trStaticModel.setEditable(false);
			}
		});
		mnuFile.addItemListener(new ItemListener() {

			public void itemStateChanged(ItemEvent e) {
				refreshSaveEnablement();
			}
		});
	}

	private void refreshSaveEnablement() {
		mnuSave.setEnabled(false);
		File selFile = m_FileChooser.getSelectedFile();
		if (selFile != null && selFile.exists() && selFile.isFile()) {
			mnuSave.setEnabled(true);
		}
	}

	public static StaticModelUI getInstance() {
		if (m_Instance == null) {
			m_Instance = new StaticModelUI();
		}
		return m_Instance;
	}

	public DomainModel getStaticModel() {
		if (m_DomainModel == null) {
			m_DomainModel = new DomainModel();
		}
		return m_DomainModel;
	}

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jSplitPane1 = new javax.swing.JSplitPane();
        jSplitPane2 = new javax.swing.JSplitPane();
        pnlTextSpec = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtSpec = new javax.swing.JTextArea();
        jPanel1 = new javax.swing.JPanel();
        btnUpdateView = new javax.swing.JButton();
        jScrollPane3 = new javax.swing.JScrollPane();
        pnlClassDiag = new ImagePanel();
        pnlStaticModel = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        trStaticModel = new javax.swing.JTree(m_DomainTreeModel);
        jMenuBar1 = new javax.swing.JMenuBar();
        mnuFile = new javax.swing.JMenu();
        mnuLoadFile = new javax.swing.JMenuItem();
        mnuSave = new javax.swing.JMenuItem();
        mnuValidate = new javax.swing.JMenuItem();

        jSplitPane1.setDividerSize(3);
        jSplitPane1.setResizeWeight(0.7);

        jSplitPane2.setDividerSize(3);
        jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane2.setResizeWeight(0.4);

        pnlTextSpec.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Requirements Description"));
        pnlTextSpec.setLayout(new java.awt.BorderLayout());

        txtSpec.setColumns(20);
        txtSpec.setRows(5);
        jScrollPane1.setViewportView(txtSpec);

        pnlTextSpec.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        btnUpdateView.setText("Update Other Views");
        btnUpdateView.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnUpdateViewActionPerformed(evt);
            }
        });
        jPanel1.add(btnUpdateView);

        pnlTextSpec.add(jPanel1, java.awt.BorderLayout.SOUTH);

        jSplitPane2.setLeftComponent(pnlTextSpec);

        pnlClassDiag.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Static Diagram")));

        javax.swing.GroupLayout pnlClassDiagLayout = new javax.swing.GroupLayout(pnlClassDiag);
        pnlClassDiag.setLayout(pnlClassDiagLayout);
        pnlClassDiagLayout.setHorizontalGroup(
            pnlClassDiagLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 442, Short.MAX_VALUE)
        );
        pnlClassDiagLayout.setVerticalGroup(
            pnlClassDiagLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 198, Short.MAX_VALUE)
        );

        jScrollPane3.setViewportView(pnlClassDiag);

        jSplitPane2.setRightComponent(jScrollPane3);

        jSplitPane1.setLeftComponent(jSplitPane2);

        pnlStaticModel.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Static Model")));

        trStaticModel.setCellEditor(new DomainTreeEditor());
        trStaticModel.setCellRenderer(m_DomainRenderer);
        jScrollPane2.setViewportView(trStaticModel);

        javax.swing.GroupLayout pnlStaticModelLayout = new javax.swing.GroupLayout(pnlStaticModel);
        pnlStaticModel.setLayout(pnlStaticModelLayout);
        pnlStaticModelLayout.setHorizontalGroup(
            pnlStaticModelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 158, Short.MAX_VALUE)
            .addGroup(pnlStaticModelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 158, Short.MAX_VALUE))
        );
        pnlStaticModelLayout.setVerticalGroup(
            pnlStaticModelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 339, Short.MAX_VALUE)
            .addGroup(pnlStaticModelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 339, Short.MAX_VALUE))
        );

        jSplitPane1.setRightComponent(pnlStaticModel);

        mnuFile.setText("File");

        mnuLoadFile.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        mnuLoadFile.setText("Load text from File");
        mnuLoadFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mnuLoadFileActionPerformed(evt);
            }
        });
        mnuFile.add(mnuLoadFile);

        mnuSave.setText("Save File");
        mnuSave.setEnabled(false);
        mnuSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mnuSaveActionPerformed(evt);
            }
        });
        mnuFile.add(mnuSave);

        mnuValidate.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F9, java.awt.event.InputEvent.CTRL_MASK));
        mnuValidate.setText("Validate Static Model");
        mnuValidate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mnuValidateActionPerformed(evt);
            }
        });
        mnuFile.add(mnuValidate);

        jMenuBar1.add(mnuFile);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 645, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 645, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 374, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 374, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	private void mnuLoadFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuLoadFileActionPerformed
		m_FileChooser.setMultiSelectionEnabled(false);
		int returnVal = m_FileChooser.showOpenDialog(null);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			if (m_FileChooser.getSelectedFile().isFile()) {
				try {
					BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(m_FileChooser.getSelectedFile())));
					String s;
					StringBuffer bf = new StringBuffer();
					while ((s = reader.readLine()) != null) {
						bf.append(s.toLowerCase() + "\n");
					}
					reader.close();
					txtSpec.setText(bf.toString());
					setTitle(m_FileChooser.getSelectedFile().getAbsolutePath());
				} catch (FileNotFoundException ex) {
					JOptionPane.showMessageDialog(null, "File not found : " + m_FileChooser.getSelectedFile(), "Error", JOptionPane.ERROR_MESSAGE);
				} catch (IOException ex) {
					JOptionPane.showMessageDialog(null, "Error reading file : " + m_FileChooser.getSelectedFile(), "Error", JOptionPane.ERROR_MESSAGE);
				}
			}
		}
	}//GEN-LAST:event_mnuLoadFileActionPerformed

	JFileChooser m_FileChooser = new JFileChooser();

	private void mnuValidateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuValidateActionPerformed
		updateStaticModelImage();
		if (StaticModelValidator.ValidateModel(m_DomainModel, OntologyUI.getInstance().getOntologyModel())) {
			updateStaticModelImage();
		}
	}//GEN-LAST:event_mnuValidateActionPerformed

	private void btnUpdateViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnUpdateViewActionPerformed
		if (!txtSpec.getText().trim().isEmpty()) {
			updateStaticModelImage();
		}
	}//GEN-LAST:event_btnUpdateViewActionPerformed

	private void mnuSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuSaveActionPerformed
		File selFile = m_FileChooser.getSelectedFile();
		if (selFile != null && selFile.exists() && selFile.isFile()) {
			try {
				PrintStream ps = new PrintStream(selFile);
				ps.print(txtSpec.getText());
				ps.close();
			} catch (FileNotFoundException ex) {
				JOptionPane.showMessageDialog(null, "File " + selFile.getPath() + " not found !");
			}
		} else {
			JOptionPane.showMessageDialog(null, "Invalid file chosen");
		}
	}//GEN-LAST:event_mnuSaveActionPerformed

		private void updateStaticModelImage() {
		String strSpec = txtSpec.getText();
		String scriptFile = System.getProperty(Const.STATIC_DIAGRAM_SCRIPT_KEY);
		File workDir = new File(scriptFile).getParentFile();
		try {
			File tempFile = File.createTempFile("dowser_", ".txt");
			PrintStream psTemp = new PrintStream(tempFile);
			psTemp.print(strSpec);
			psTemp.close();
			String strImg = workDir.getPath() + File.separator + "static_diag.png";
			String strCommand = new File(scriptFile).getAbsolutePath() + " " + tempFile.getAbsolutePath() + " " + strImg;
			Process p = Runtime.getRuntime().exec(strCommand, null, workDir);
			p.waitFor();
			tempFile.delete();
			File flModel = new File(workDir.getPath() + File.separator + "static_model.java");
			DomainModel model = ModelParser.parseModel(flModel.getAbsolutePath());
			flModel.delete();
			m_DomainTreeModel.setModel(model);
			m_DomainModel = model;
			File flImage = new File(strImg);
			((ImagePanel) pnlClassDiag).setImageFile(flImage);
			pnlClassDiag.repaint();
			flImage.delete();
		} catch (IOException ex) {
			ex.printStackTrace(System.err);
		} catch (InterruptedException ex) {
			ex.printStackTrace(System.err);
		}
	}

	private static StaticModelUI m_Instance;

	/**
	 * @param args the command line arguments
	 */
	public static void main(String args[]) {
		java.awt.EventQueue.invokeLater(new Runnable() {

			public void run() {
				getInstance().setVisible(true);
			}
		});
	}

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnUpdateView;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JSplitPane jSplitPane2;
    private javax.swing.JMenu mnuFile;
    private javax.swing.JMenuItem mnuLoadFile;
    private javax.swing.JMenuItem mnuSave;
    private javax.swing.JMenuItem mnuValidate;
    private javax.swing.JPanel pnlClassDiag;
    private javax.swing.JPanel pnlStaticModel;
    private javax.swing.JPanel pnlTextSpec;
    private javax.swing.JTree trStaticModel;
    private javax.swing.JTextArea txtSpec;
    // End of variables declaration//GEN-END:variables

}
