/**
 * Class StatementCommandButtons
 * This class is in charge of creating the buttons that will perform some
 * operations on the svg file being edited (actually on the its image DOM Tree)
 * Of course it implements such operations thanks to innerclasses
 * with event listeners.
 **/

package axsvg.edition;

import axsvg.*;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import fr.dyade.koala.dom.*;
import fr.dyade.koala.dom.util.*;
import org.w3c.dom.*;
import java.util.*;

public class StatementCommandButtons {

    //The Xstatement allows the access to the comboboxes selected item,
    //and to the DocumentMixte being edited.
    private final Xstatement xstatement;

    //The text area crated by the Editor class in wich all character output
    //inherent to the methods implemented here will be redirected.
    private final JTextArea textArea;

    //The table (created by this object) contening the attributes of the
    //node (virtual or not) image of the statement being selected.
    private final AttributeJTable table;


    /**
     * Method StatementCommandButtons
     * the constructor of the class.
     * @param the Xstatement that will give the datas needed by the
     * operations to be done on the processed DocumentMixte (basicaly
     * the selected items of the comboBoxes and the DocumentMixte itself).
     * @param the text area in wich all output generated by such operations
     * will be redirected (thanx to a custom made PrintStream implemented
     * by the class TextAreaPrintStream).
     **/
    public StatementCommandButtons(Xstatement xstat,JTextArea text ) {
	xstatement = xstat;
	textArea = text;
	table = new AttributeJTable(new ListOfAttributeNames());
	System.setOut(new TextAreaPrintStream(textArea, System.out));
    }


    /**
     * Method findStatementNode
     * @return the Node of the rdf part of the processed Document 
     * corresponding to the currently selected statement: Such a Node admits
     * as name the selected predicate, as 'resource' attribute the selected
     * object, and as parent node the rdf Node wich has the selected subject
     * as 'about' attribute.
     * if such a Node does not exist, it returns null.
     **/
    private Node findStatementNode() {
	Hashtable tableRDF = xstatement.docMixte.getTableRDF();
	String subject = "#"+(String)xstatement.subjectBox.getSelectedItem();
	String object = "#"+(String)xstatement.objectBox.getSelectedItem();
	String predicate = (String)xstatement.predicateBox.getSelectedItem();
	String meaning = (String)xstatement.propertiesTable.get(predicate);
	AElementRDF eltRDF = (AElementRDF)tableRDF.get(subject);
	if(eltRDF != null) {
	    Node node = eltRDF.getGenerator().getFirstChild();
	    while(node != null) {
		String nomPropriete = node.getNodeName();
		//removes the ns prefix of the propertyname (should be 'axsvg')
		nomPropriete = nomPropriete.substring(
					    nomPropriete.indexOf(":")+1);
		if(nomPropriete.equalsIgnoreCase(predicate)) {
		    if(object.equalsIgnoreCase(((Element)node).getAttribute(
			     "resource")) || meaning.endsWith("(by value)" )) {
			return(node);
		    }
		    if(((Element)node).getAttribute("resource").equals("")){
			Node bag = node.getFirstChild();
			while(bag != null) {
			    if(bag.getNodeName().equalsIgnoreCase("rdf:Bag")) {
				Node li = bag.getFirstChild();
				while(li != null) {
				    if(li.getNodeName().equalsIgnoreCase(
								   "rdf:li")) {
					if(object.equalsIgnoreCase(
				      ((Element)li).getAttribute("resource"))){
					    return(li);
					}
				    }
				    li = li.getNextSibling();
				}
				break;
			    }
			    bag = bag.getNextSibling();
			}
		    }
		}
		node = node.getNextSibling();
	    }
	}
	return(null);
    }

	
    /**
     * Method createStatementCommandButtons
     * @return a Component which contains the 4 command buttons:
     * - check statement (prints out the selected statement meaning)
     * - validate statement (add the selected statement to the RDF DOM of the
     * processed document)
     * - remove statement (remove the selected statement from the RDF DOM of
     * the processed document. If such a statement does'nt exist, does nothing)
     * - check whole desc (prints out the whole description of the processed
     * document, as axsvg.jar would do).
     * All these operations are implemented in an inner class just after the
     * definition of each button, as event listeners.
     **/
    public Component createStatementCommandButtons() {
      

	//Button Check Statement
	final JButton checkStatement = new JButton("Check Statement");
        checkStatement.setMnemonic(KeyEvent.VK_C);
	checkStatement.addMouseListener(new MouseListener() {
	    public void mouseEntered(MouseEvent e) {
                if(findStatementNode() != null) checkStatement.setText(
							  "Existing Already!");
             }
	    public void mouseExited(MouseEvent e) {
		checkStatement.setText("Check Statement");	
	    }
	    public void mousePressed(MouseEvent e) {}
	    public void mouseReleased(MouseEvent e) {}
	    public void mouseClicked(MouseEvent e) {}
	});
	checkStatement.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
		String subject=(String)xstatement.subjectBox.getSelectedItem();
		String object=(String)xstatement.objectBox.getSelectedItem();
		String predicate=
		    (String)xstatement.predicateBox.getSelectedItem();
		String meaning=
		    (String)xstatement.propertiesTable.get(predicate);
		Element elt = (Element)findStatementNode();
		table.copyAttributesToTable(elt);
		if(meaning.endsWith("(by value)")) {
		    meaning = meaning.substring(0, meaning.indexOf(
							      "(by value)")-1);
		    textArea.setText("The entity "+subject+" "+meaning); 
		}
		else {
		    textArea.setText("The entity "+subject+" "+meaning+
				     " the entity "+object);
		}
		if(elt != null) {
		    String attrValue;
		    ListOfAttributeNames attributeNames =
			new ListOfAttributeNames();
		    String name = attributeNames.getNextAttributeName();
		    while(name != null) {
			attrValue = elt.getAttribute(name);
			if(!attrValue.equalsIgnoreCase("")) {
			    textArea.append(", "+
			        attributeNames.getMeaning(name)+" "+attrValue);
			}
			name = attributeNames.getNextAttributeName();
		    }
		}
		textArea.append(".");
	    }
	});
	


	//Button Validate Statement
	JButton validateStatement = new JButton("Validate Statement");
        validateStatement.setMnemonic(KeyEvent.VK_V);
	validateStatement.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
		Hashtable tableRDF = xstatement.docMixte.getTableRDF();
		String subject = "#"+
		    (String)xstatement.subjectBox.getSelectedItem();
		String object = "#"+
		    (String)xstatement.objectBox.getSelectedItem();
		String predicate = 
		    (String)xstatement.predicateBox.getSelectedItem();
		String meaning = 
		    (String)xstatement.propertiesTable.get(predicate);
		AElementRDF eltRDF = (AElementRDF)tableRDF.get(subject);
		Element found = (Element)findStatementNode();
		if(found != null) {
		    table.copyTableToAttributes(found);
		    return;
		}
		if(eltRDF != null) {		    
		    Node node = eltRDF.getGenerator().getFirstChild();
		    for(;;) {
			if(node == null) {
			    Element elt=new GenericElement("axsvg:"+predicate,
                         (AbstractDocument)xstatement.docMixte.getGenerator());
			    if(!meaning.endsWith("(by value)")) {
				elt.setAttribute("resource",object);
			    }
			    table.copyTableToAttributes(elt);
			    eltRDF.getGenerator().appendChild(elt);
			    break;
			}
			String nomPropriete = node.getNodeName();
			nomPropriete = nomPropriete.substring(
						  nomPropriete.indexOf(":")+1);
			if(nomPropriete.equalsIgnoreCase(predicate)) {
			   if(((Element)node).getAttribute("resource").equals(
									  "")){
				Node bag = node.getFirstChild();
				while(bag != null) {
				    if(bag.getNodeName().equalsIgnoreCase(
								  "rdf:Bag")) {
					 Element elt=new GenericElement(
								    "rdf:li",
		         (AbstractDocument)xstatement.docMixte.getGenerator());
					 elt.setAttribute("resource",object);
					 table.copyTableToAttributes(elt);
					 bag.appendChild(elt);
					 break;
				    }
				    bag = bag.getNextSibling();
				}
			    }
			    else {
				AbstractNode toBeChanged = (AbstractNode)node;
				Element prop =  new GenericElement("axsvg:"+
								   predicate,
                         (AbstractDocument)xstatement.docMixte.getGenerator());
				
				Element bag = new GenericElement("rdf:Bag",
                        (AbstractDocument)xstatement.docMixte.getGenerator());
 
				Element newOne =  new GenericElement("rdf:li",
                         (AbstractDocument)xstatement.docMixte.getGenerator());
				toBeChanged.setNodeName("rdf:li");
				newOne.setAttribute("resource",object);
				table.copyTableToAttributes(newOne);
				eltRDF.getGenerator().insertBefore(prop,
								  toBeChanged);
				eltRDF.getGenerator().removeChild(toBeChanged);
				
				prop.appendChild(bag);
				bag.appendChild(toBeChanged);
				bag.appendChild(newOne);
			    }
			    break;
			}
			node = node.getNextSibling();
		    }
		}
		else {
		    Element elt = new GenericElement("rdf:Description",
                       (AbstractDocument)xstatement.docMixte.getGenerator());  
		    elt.setAttribute("about", subject);
		    xstatement.docMixte.getRDFRoot().appendChild(elt);
		    Element child = new GenericElement("axsvg:"+
              predicate, (AbstractDocument)xstatement.docMixte.getGenerator());
		    if(!meaning.endsWith("(by value)")) {
			child.setAttribute("resource",object);
		    }
		    table.copyTableToAttributes(child);
		    elt.appendChild(child);
		    tableRDF.put(subject, new AElementRDF(elt));
		}
	    }
	});


	//Button remove Statement
	JButton remove = new JButton("Remove Statement");
        remove.setMnemonic(KeyEvent.VK_R);
	remove.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
		Hashtable tableRDF = xstatement.docMixte.getTableRDF();
		String subject = "#"+
		    (String)xstatement.subjectBox.getSelectedItem();
		String predicate =
		    (String)xstatement.predicateBox.getSelectedItem();
		AElementRDF eltRDF = (AElementRDF)tableRDF.get(subject);
		Node toBeRemoved = findStatementNode();

		if(toBeRemoved == null) return;
		if(toBeRemoved.getNodeName().equalsIgnoreCase("rdf:li")) {
		    int numberOfLiChild = 0;
		    AbstractNode toBeTransfered = null;
		    Node bag = toBeRemoved.getParentNode();
		    bag.removeChild(toBeRemoved);
		    Node li = bag.getFirstChild();		    
		    while(li != null) {
			if(li.getNodeName().equalsIgnoreCase("rdf:li")) {
			    numberOfLiChild++;
			    toBeTransfered = (AbstractNode)li;
			}
			li = li.getNextSibling();
		    }
		    if(numberOfLiChild == 1) {
			Node node = bag.getParentNode();
			toBeTransfered.setNodeName("axsvg:"+predicate);
			bag.removeChild(toBeTransfered);
			eltRDF.getGenerator().insertBefore(toBeTransfered,
							   node);
			eltRDF.getGenerator().removeChild(node);
		    }
		}
		else {
		    eltRDF.getGenerator().removeChild(toBeRemoved);
		}
	    }
	});


	//Button check whole description.
	JButton checkWholeDesc = new JButton("Check whole desc");
        checkWholeDesc.setMnemonic(KeyEvent.VK_D);
	checkWholeDesc.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
		try {
		DocumentMixte docMixte = xstatement.docMixte;
		textArea.setText("");
		//calls the static method used in axsvg.jar to ouptut the desc.
		//Such a method uses 'System.out.print' calls to perform
		//the output. Thanx to System.setOut method used in the 
		//constructor, we set as output stream  the textArea of 
		//the editor.
		Descriptor.printWholeDesc(docMixte);
		docMixte.buildTableSVG(docMixte.getSVGRoot());
		docMixte.buildTableRDF(docMixte.getRDFRoot());
		} catch (Exception exception) {}
	    }
	});
	
	//Create the panel that contents the buttons
        JPanel pane = new JPanel();
        
        pane.setLayout(new GridLayout(0, 1));
	pane.add(checkStatement);
	pane.add(validateStatement);
	pane.add(remove);
	pane.add(checkWholeDesc);

	//Create the Attributes table
	JPanel atrTable = new JPanel();
	atrTable.add(table);
	atrTable.setBorder(BorderFactory.createEmptyBorder(
                                        5, //top
                                        0, //left
                                        0, //bottom
                                        0) //right
                                        );

	//Create the panel which constitutes the Control Area (attribute table
	//+ buttons)
	JPanel controlArea = new JPanel();
	controlArea.setLayout(new BorderLayout());
	controlArea.add(atrTable, BorderLayout.CENTER);
	controlArea.add(pane, BorderLayout.NORTH);

	controlArea.setBorder(BorderFactory.createCompoundBorder(
			  BorderFactory.createTitledBorder("Controls"),
			  BorderFactory.createEmptyBorder(
                                        5, //top
                                        5, //left
                                        5, //bottom
                                        5) //right
                                        ));

	return(controlArea);
    }
}
