/**
 * CertainTrust Demonstrator in Java for CONSENSUS and DISCOUNTING
 * 
 * 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 DemonstratorCD extends JApplet {
	private static final long serialVersionUID = -7397289934413234935L;
	
	// the CertainTrust data objects
	private CertainTrust CONOperand1;
	private CertainTrust CONOperand2;
	private CertainTrust CONResult;
	private CertainTrust DISOperand1;
	private CertainTrust DISOperand2;
	private CertainTrust DISResult;
	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 DemonstratorCD() {
		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 CONSENSUS operation
		JPanel CONPanel = new JPanel();
		CONPanel.setLayout(new FlowLayout());
		
		this.CONOperand1 = new CertainTrust(N);
		this.HTIAndOperand1 = new CertainTrustHTI(this.CONOperand1);
		CONPanel.add(this.HTIAndOperand1);

		CONPanel.add(new Label("CONSENSUS"));
		
		this.CONOperand2 = new CertainTrust(N);
		this.HTIAndOperand2 = new CertainTrustHTI(this.CONOperand2);
		CONPanel.add(this.HTIAndOperand2);
		
		CONPanel.add(new Label("="));
		
		this.CONResult = new CertainTrust(N);
		Map<String,String> htiConfig = new HashMap<String, String>();
		htiConfig.put("readonly", "true");
		this.HTIAndResult = new CertainTrustHTI(this.CONResult, htiConfig);
		CONPanel.add(this.HTIAndResult);
		
		constraints.insets = new Insets(30, 0, 10, 0);
		constraints.gridwidth = GridBagConstraints.REMAINDER;
		add(CONPanel, constraints);
		
		
		// operands and result for DISCOUNTING operation
		JPanel DISPanel = new JPanel();
		DISPanel.setLayout(new FlowLayout());
		
		this.DISOperand1 = new CertainTrust(N);
		this.HTIOrOperand1 = new CertainTrustHTI(this.DISOperand1);
		DISPanel.add(this.HTIOrOperand1);

		DISPanel.add(new Label("DISCOUNTING"));
		
		this.DISOperand2 = new CertainTrust(N);
		this.HTIOrOperand2 = new CertainTrustHTI(this.DISOperand2);
		DISPanel.add(this.HTIOrOperand2);
		
		DISPanel.add(new Label("="));
		
		this.DISResult = new CertainTrust(N);
		this.HTIOrResult = new CertainTrustHTI(this.DISResult, htiConfig);
		DISPanel.add(this.HTIOrResult);
		
		add(DISPanel, 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 CONSENSUS operation
		CONSENSUSObserver conObserver = new CONSENSUSObserver(CONOperand1, CONOperand2, CONResult);
		CONOperand1.addObserver(conObserver);
		CONOperand2.addObserver(conObserver);
		
		// do an initial update
		conObserver.update(null, null);
		
		
		// same for the OR operation
		DISCOUNTINGObserver disObserver = new DISCOUNTINGObserver(DISOperand1, DISOperand2, DISResult);
		DISOperand1.addObserver(disObserver);
		DISOperand2.addObserver(disObserver);
		disObserver.update(null, null);
	}
}
