/**
 * CertainTrust Demonstrator in Java
 * 
 * Demonstrates some capabilities of the CertainTrust SDK
 * using a Java applet that interactively calculates
 * AND and OR of two CertainTrust data objects and
 * visually displays both the input objects and the output.
 * 
 * @author	Florian Volk <florian.volk@cased.de>
 */

import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Label;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JApplet;
import javax.swing.JPanel;

import CertainTrust.CertainTrust;
import CertainTrust.CertainTrustHTI;


public class Demonstrator extends JApplet {
	private static final long serialVersionUID = -7397289934413234935L;
	
	// the CertainTrust data objects
	private CertainTrust AndOperand1;
	private CertainTrust AndOperand2;
	private CertainTrust AndResult;
	private CertainTrust OrOperand1;
	private CertainTrust OrOperand2;
	private CertainTrust OrResult;
	private static int N = 10;
	
	// the HTI objects that hold the CertainTrust data
	private CertainTrustHTI HTIAndOperand1;
	private CertainTrustHTI HTIAndOperand2;
	private CertainTrustHTI HTIAndResult;
	private CertainTrustHTI HTIOrOperand1;
	private CertainTrustHTI HTIOrOperand2;
	private CertainTrustHTI HTIOrResult;
	

	public Demonstrator() {
		setupUI();
		setupLogic();
	}
	
	@Override
	public void init() {
		// make sure nothing is cut off due to a too small applet
		setSize(1200, 500);
	}
	
	/**
	 * setupUI() creates the user interface and
	 * binds all HTIs to the related CertainTrust data objects
	 */
	private void setupUI() {
		// use GridBayLayout to align all the elements
		GridBagConstraints constraints = new GridBagConstraints();
		setLayout(new GridBagLayout());
		
		// title line "Demonstrator for CertainTrust"
		constraints.gridwidth = GridBagConstraints.REMAINDER;
		constraints.gridheight = 1;
		constraints.insets = new Insets(10, 0, 0, 0);
		Label title = new Label("Demonstrator for CertainTrust");
		title.setFont(new Font("Sans Serif", Font.BOLD, 24));
		add(title, constraints);
		
		// subtitle line
		constraints.insets = new Insets(0, 0, 10, 0);
		add(new Label("CertainTrust provides a means for the evaluation of propositional logic terms under uncertainty."), constraints);
		
		
		// operands and result for AND operation
		JPanel AndPanel = new JPanel();
		AndPanel.setLayout(new FlowLayout());
		
		this.AndOperand1 = new CertainTrust(N);
		this.HTIAndOperand1 = new CertainTrustHTI(this.AndOperand1);
		AndPanel.add(this.HTIAndOperand1);

		AndPanel.add(new Label("AND"));
		
		this.AndOperand2 = new CertainTrust(N);
		this.HTIAndOperand2 = new CertainTrustHTI(this.AndOperand2);
		AndPanel.add(this.HTIAndOperand2);
		
		AndPanel.add(new Label("="));
		
		this.AndResult = new CertainTrust(N);
		Map<String,String> htiConfig = new HashMap<String, String>();
		htiConfig.put("readonly", "true");
		this.HTIAndResult = new CertainTrustHTI(this.AndResult, htiConfig);
		AndPanel.add(this.HTIAndResult);
		
		constraints.insets = new Insets(30, 0, 10, 0);
		constraints.gridwidth = GridBagConstraints.REMAINDER;
		add(AndPanel, constraints);
		
		
		// operands and result for OR operation
		JPanel OrPanel = new JPanel();
		OrPanel.setLayout(new FlowLayout());
		
		this.OrOperand1 = new CertainTrust(N);
		this.HTIOrOperand1 = new CertainTrustHTI(this.OrOperand1);
		OrPanel.add(this.HTIOrOperand1);

		OrPanel.add(new Label("OR"));
		
		this.OrOperand2 = new CertainTrust(N);
		this.HTIOrOperand2 = new CertainTrustHTI(this.OrOperand2);
		OrPanel.add(this.HTIOrOperand2);
		
		OrPanel.add(new Label("="));
		
		this.OrResult = new CertainTrust(N);
		this.HTIOrResult = new CertainTrustHTI(this.OrResult, htiConfig);
		OrPanel.add(this.HTIOrResult);
		
		add(OrPanel, constraints);
	}

	/**
	 * setupLogic() implements the wiring between the different CertainTrust data objects,
	 * the HTIs get updates automatically due to the used Observer pattern
	 */
	private void setupLogic() {
		// wire all components forming the AND operation
		ANDObserver andObserver = new ANDObserver(AndOperand1, AndOperand2, AndResult);
		AndOperand1.addObserver(andObserver);
		AndOperand2.addObserver(andObserver);
		
		// do an initial update
		andObserver.update(null, null);
		
		
		// same for the OR operation
		ORObserver orObserver = new ORObserver(OrOperand1, OrOperand2, OrResult);
		OrOperand1.addObserver(orObserver);
		OrOperand2.addObserver(orObserver);
		orObserver.update(null, null);
	}
}
