/////////////////////////////////////////////////////////////////////////
//
// © Institute for Software Science, University of Vienna, 2004
//
// Copyright in this software belongs to Institute for Software Science, 
// University of Vienna, Nordbergstrasse 15/C/3, 1090 Vienna, Austria
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
//	Created By :		Gerhard Engelbrecht
//	Created Date :		2004/08/15
//	Created for Project:	GEMSS
//
////////////////////////////////////////////////////////////////////////
//
// Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//	Last commit info:	$Author: gerry $
//					$Date: 2004/08/09 16:02:34 $
//					$Revision: 1.2 $
//
/////////////////////////////////////////////////////////////////////////

package at.ac.univie.iss.proxies.qos.examples;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.logging.*;
import java.util.*;
import at.ac.univie.iss.descriptors.qos.*;
import java.text.*;

public class BasicQoSExampleWithFrame extends Frame implements ActionListener {
	
	Logger logger = Logger.getLogger(BasicQoSExampleWithFrame.class.getName());
	
	
	Label outputLabel = new Label("GEMSS Component Output/Logging:");
	TextArea output = new TextArea();
	Label detailsLabel = new Label("REQUEST DETAILS:");
	Label offerLabel = new Label("OFFERS and STATUS:");
	Panel offers = new Panel();
	Button start = new Button("Obtain new Offers");
	Button confirm = new Button("Confirm Offer and Start");
	Button abort = new Button("Abort");
	Button quit = new Button("Quit");
	
	TextField price = new TextField(25);
	TextField begin = new TextField(25);
	TextField endT = new TextField(25);
	
	TextArea reqDesc = new TextArea(80,80);

	SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
	
	
	PrintStream outputStream  = 
	   new PrintStream(
	     new FilteredStream(
	       new ByteArrayOutputStream()));
	
	boolean logFile;
	
	//Vector offerVec;
	
	BasicQoSExampleWithFrame(boolean logFile) {
   	
		Calendar beginCa = Calendar.getInstance();
        Calendar endCa = Calendar.getInstance();		// current time plus one day
		endCa.roll( Calendar.HOUR_OF_DAY, 2); //, endCa.get(Calendar.HOUR_OF_DAY)+1);

		begin.setText(sdf.format(beginCa.getTime()));
		endT.setText(sdf.format(endCa.getTime()));
		price.setText("100");

        RequestDescriptor r = new RequestDescriptorImpl();
        r.setPerformanceParameter("TestParam1", "100");
        r.setPerformanceParameter("TestParam2", "200");

		reqDesc.setText(r.toString());

		this.logFile = logFile;
		
		reqDesc.setFont(new Font ("SansSerif", Font.PLAIN, 12));
		price.setFont(new Font ("SansSerif", Font.PLAIN, 12));
		begin.setFont(new Font ("SansSerif", Font.PLAIN, 12));
		endT.setFont(new Font ("SansSerif", Font.PLAIN, 12));

		start.addActionListener(this);
		confirm.addActionListener(this);
		abort.addActionListener(this);
		quit.addActionListener(this);
		
		
		System.setOut(outputStream);
		System.setErr(outputStream);
		setTitle("Basic QoS Example");
		//setSize(500,300);
		setLayout(new BorderLayout());
		add(new Panel(), BorderLayout.NORTH);
		add(new Panel(), BorderLayout.WEST);
		add(new Panel(), BorderLayout.SOUTH);
		add(new Panel(), BorderLayout.EAST);
		Panel bigPanel = new Panel();
		bigPanel.setLayout(new GridLayout(3,1));
		//bigPanel.setSize(800,600);
		add(bigPanel, BorderLayout.CENTER);
		
		
		Panel upperPanel = new Panel();

		upperPanel.setLayout(new BorderLayout());
		outputLabel.setFont(new Font ("SansSerif", Font.BOLD, 16));
		upperPanel.add(outputLabel, BorderLayout.NORTH);
		upperPanel.add(output, BorderLayout.CENTER);
		detailsLabel.setFont(new Font ("SansSerif", Font.BOLD, 16));
		upperPanel.add(detailsLabel, BorderLayout.SOUTH);
		bigPanel.add(upperPanel);
		
		Panel middlePanel = new Panel();
		
		middlePanel.setLayout(new BorderLayout(10, 10));
		
		offerLabel.setFont(new Font ("SansSerif", Font.BOLD, 16));
		middlePanel.add(offerLabel, BorderLayout.SOUTH);
		
		Panel qosDescPanel = new Panel();
		qosDescPanel.setLayout(new BorderLayout());
		Label initQoSDescLabel = new Label("Initial QoS Descriptor:");
		initQoSDescLabel.setFont(new Font ("SansSerif", Font.BOLD, 12));
		qosDescPanel.add(initQoSDescLabel, BorderLayout.NORTH);
		
		Panel lines = new Panel();
		lines.setLayout(new GridLayout(7, 1));
		Label li1 = new Label("Objective Price (Euro):");
		li1.setFont(new Font ("SansSerif", Font.PLAIN, 12));
		Label li2 = new Label("Objective Begin (date):");
		li2.setFont(new Font ("SansSerif", Font.PLAIN, 12));
		Label li3 = new Label("Objective End (date):");
		li3.setFont(new Font ("SansSerif", Font.PLAIN, 12));
		
		lines.add(li1);
		lines.add(price);
		lines.add(li2);
		lines.add(begin);
		lines.add(li3);
		lines.add(endT);
		lines.add(new Panel());


		qosDescPanel.add(lines, BorderLayout.CENTER);
		
		
		
		middlePanel.add(qosDescPanel, BorderLayout.WEST);

		Panel textAreaPanel = new Panel();
		textAreaPanel.setLayout(new BorderLayout());
		
		Label textAreaLabel = new Label("Request Descriptor:");
		textAreaLabel.setFont(new Font ("SansSerif", Font.BOLD, 12));
		textAreaPanel.add(textAreaLabel, BorderLayout.NORTH);
		
		textAreaPanel.add(reqDesc, BorderLayout.CENTER);
		
		middlePanel.add(textAreaPanel, BorderLayout.CENTER);
		
		bigPanel.add(middlePanel);
		
		Panel lowerPanel = new Panel();

		lowerPanel.setLayout(new BorderLayout());
		//lowerPanel.add(spbe, BorderLayout.NORTH);
		lowerPanel.add(offers, BorderLayout.CENTER);

		Panel buttonsPanel = new Panel();
		buttonsPanel.setLayout(new GridLayout(1, 4, 20, 20));
		abort.setEnabled(false);
		confirm.setEnabled(false);
		buttonsPanel.add(start);
		buttonsPanel.add(confirm);
		buttonsPanel.add(abort);
		buttonsPanel.add(quit);

		lowerPanel.add(buttonsPanel, BorderLayout.SOUTH);

		bigPanel.add(lowerPanel);



		this.pack();
		setSize(1300, 900);
		
		
		displayLog();
		addWindowListener
			(new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					dispose();
				}
			}
		);
	}

	class FilteredStream extends FilterOutputStream {
		public FilteredStream(OutputStream aStream) {
			super(aStream);
		}
				
		public void write(byte b[]) throws IOException {
    			
			String aString = new String(b);
			output.append(aString);
		}
				
		public void write(byte b[], int off, int len) throws IOException {
    			
			String aString = new String(b , off , len);
			output.append(aString);
    			
			if (logFile) {
    			
				FileWriter aWriter = new FileWriter("error.log", true);
				aWriter.write(aString);
				aWriter.close();
			}
		}
	}

	public void displayLog() {
		Dimension dim = getToolkit().getScreenSize();
		Rectangle abounds = getBounds();
		Dimension dd = getSize();
		setLocation((dim.width - abounds.width) / 2,
			(dim.height - abounds.height) / 2);
		setVisible(true);
		requestFocus();
	}
	
	private CheckboxGroup group;
	
	private TThread thread = new TThread();

	public void	actionPerformed(ActionEvent e) {

		if (e.getActionCommand().equals("Abort")) {
				
			thread.stop(); 
			start.setEnabled(true);
			confirm.setEnabled(false);
			abort.setEnabled(false);
			return;
		}
		thread = new TThread();
		thread.setEvent(e);
		thread.start();

	} 


    static private String formatCalendar(Calendar calendar) {
		
        SimpleDateFormat dateAndTimeFormatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss z"); 

        return (dateAndTimeFormatter.format(new Date(calendar.getTimeInMillis())));
    }

	static private String formatDouble(double number) {
		
		DecimalFormat doubleFormatter = new DecimalFormat("###,###.##");
		return (doubleFormatter.format(number));
	}

	public static void main(String s[]){

	   BasicQoSExampleWithFrame basicQoSExampleWithFrame = new BasicQoSExampleWithFrame(false);
	}


	OfferAndURI[] offerAndURIs = null;

	private class TThread extends Thread {
		
		ActionEvent e;

		public TThread() {
		}
		public void setEvent(ActionEvent e) {
			this.e = e;
		}

		public void run() {

			try {
				
				BasicQoSExample example = new BasicQoSExample();
				//logger.log(Level.SEVERE, "INFO");
				
				
				//System.out.println("Event: " +  e.getActionCommand());
				
				if (e.getActionCommand().equals("Obtain new Offers")) {
					
					abort.setEnabled(true);
					confirm.setEnabled(false);
				
					String rd = reqDesc.getText();
        			RequestDescriptor rDesc = new RequestDescriptorImpl(rd);
    	
			        QoSDescriptor qDesc = new QoSDescriptorImpl();

					qDesc.setProviderName("ISS - Provider");
					qDesc.setConsumerName("ISS - Consumer");
					
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
					
					Calendar beginC = Calendar.getInstance();
					beginC.setTime(sdf.parse(begin.getText()));
	 
        			Calendar endC = Calendar.getInstance();		// current time plus one day
					endC.setTime(sdf.parse(endT.getText()));
		
        			qDesc.setObjectivePrice(Double.parseDouble(price.getText()));
			        qDesc.setObjectiveBeginTime(beginC);
        			qDesc.setObjectiveEndTime(endC);

                    logger.log(Level.INFO, "Running discovery.");
                    String[] services = example.runDiscovery();

                    logger.log(Level.INFO, "Requeting offers");
                    offerAndURIs = example.requestOffers(services, rDesc, qDesc);


					group = new CheckboxGroup();
					
					offers.removeAll();
					validate();
					offers.setLayout(new GridLayout(offerAndURIs.length, 1));
					
					for (int count = 0; count < offerAndURIs.length; count++) {
						

						QoSDescriptor qosDesc = offerAndURIs[count].getOffer();
						
						Panel oPanel = new Panel();
						oPanel.setLayout(new BorderLayout());
						
						Checkbox cb = new Checkbox("SERVICE " + (count+1) + ":", group, (count == 0));
						cb.setFont(new Font ("SansSerif", Font.BOLD, 14));
	
						//Label l0 = new Label("SERVICE " + (count+1) + ":");
						//l0.setFont(new Font ("SansSerif", Font.BOLD, 14));
						Label l1 = new Label("Address:" +  offerAndURIs[count].getURI());
						l1.setFont(new Font ("SansSerif", Font.PLAIN, 14));
						Label l2 = new Label("Price: " + formatDouble(qosDesc.getObjectivePrice()) + " Euro");
						l2.setFont(new Font ("SansSerif", Font.PLAIN, 14));
						Label l3 = new Label("Begin: " + formatCalendar(qosDesc.getObjectiveBeginTime()));
						l3.setFont(new Font ("SansSerif", Font.PLAIN, 14));
						Label l4 = new Label("End: " + formatCalendar(qosDesc.getObjectiveEndTime()));
						l4.setFont(new Font ("SansSerif", Font.PLAIN, 14));
	
						double mins = (double)(qosDesc.getObjectiveEndTime().getTimeInMillis() - qosDesc.getObjectiveBeginTime().getTimeInMillis())/60000;
						Label l5 = new Label("Service Runtime: " + formatDouble(mins) + " minutes");
						l5.setFont(new Font ("SansSerif", Font.PLAIN, 14));
	
						Panel desc = new Panel();
						desc.setLayout(new GridLayout(7, 1));
	
						desc.add(new Panel());
						desc.add(l1);
						desc.add(l2);
						desc.add(l3);
						desc.add(l4);
						desc.add(l5);
						desc.add(new Panel());
						
						oPanel.add(cb, BorderLayout.WEST);
						oPanel.add(desc, BorderLayout.CENTER);
					
						offers.add(oPanel);
					}
					validate();
					abort.setEnabled(false);
					confirm.setEnabled(true);
	
				}
				if (e.getActionCommand().equals("Confirm Offer and Start") && (offerAndURIs != null)) {
	
					start.setEnabled(false);
					confirm.setEnabled(false);
					abort.setEnabled(true);
					
					
					Checkbox cb = group.getSelectedCheckbox();
					
					System.out.println("CB: " + cb.getLabel());
					int offerNum = Integer.parseInt(cb.getLabel().substring(8,9))-1;
					
					System.out.println("offerNum: " + offerNum);
					
					//Offer offer = (Offer)offerVec.get(offerNum);
	
					offers.removeAll();
	
					QoSDescriptor qosDesc = offerAndURIs[offerNum].getOffer();
					
					
					Label l0 = new Label("SELECTED SERVICE " + (offerNum+1) + ":");
					l0.setFont(new Font ("SansSerif", Font.BOLD, 14));
					Label l1 = new Label("Address:" +  offerAndURIs[offerNum].getURI());
					l1.setFont(new Font ("SansSerif", Font.PLAIN, 14));
					Label l2 = new Label("Price: " + formatDouble(qosDesc.getObjectivePrice()) + " Euro");
					l2.setFont(new Font ("SansSerif", Font.PLAIN, 14));
					Label l3 = new Label("Begin: " + formatCalendar(qosDesc.getObjectiveBeginTime()));
					l3.setFont(new Font ("SansSerif", Font.PLAIN, 14));
					Label l4 = new Label("End: " + formatCalendar(qosDesc.getObjectiveEndTime()));
					l4.setFont(new Font ("SansSerif", Font.PLAIN, 14));
	
					double mins = (double)(qosDesc.getObjectiveEndTime().getTimeInMillis() - qosDesc.getObjectiveBeginTime().getTimeInMillis())/60000;
					Label l5 = new Label("Service Runtime: " + formatDouble(mins) + " minutes");
					l5.setFont(new Font ("SansSerif", Font.PLAIN, 14));
	
					Panel desc = new Panel();
					desc.setLayout(new GridLayout(8, 1));
	
					desc.add(new Panel());
					desc.add(l0);
					desc.add(l1);
					desc.add(l2);
					desc.add(l3);
					desc.add(l4);
					desc.add(l5);
					desc.add(new Panel());
						
					offers.add(desc);
					
					Label progress = new Label("PROGRESS: ");
					progress.setFont(new Font ("SansSerif", Font.BOLD, 14));
					progress.setForeground(Color.BLUE);
					
					offers.add(progress);
					
	
					validate();
	
					example.confirmOffer(offerAndURIs[offerNum]);
					
					WThread wThread = new WThread(progress, example);
					wThread.start();
					
					example.runJobHandling(offerAndURIs[offerNum].getOffer().getSLAName().substring(8), offerAndURIs[offerNum].getURI());
	
					start.setEnabled(true);
				}
				if (e.getActionCommand().equals("Abort")) {
				
					// not implemented yet
	
				}
				if (e.getActionCommand().equals("Quit")) {
				
					dispose();
				}
	
			}
			catch (Exception ex) {
				
				ex.printStackTrace();
			}		
			
		}
	}


	private class WThread extends Thread {
	
	    private Label progress = null;
	    private BasicQoSExample example = null;

    	public WThread(Label progress, BasicQoSExample example) {
    	    
    	    this.progress = progress;
    	    this.example = example;
		}


		public void run() {

            boolean finished = false;
            
            while (!finished) {
                
                try {
                    Thread.sleep(1000);
                }
                catch (Exception e) {
            }

                String status = example.status.toString();
                
                progress.setText("PROGRESS: " + status.toString());
                
                if (status.endsWith("-> Acknowledged!!!")) {
                    finished = true;
                }  
            }
        }
    }
}