package exampleAlgorithms;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import api.Algorithm;
import ui.controller.Control;
import ui.model.DecoratedHolonObject.HolonObjectState;
import ui.model.DecoratedNetwork;
import ui.model.DecoratedState;

public class ExampleFitnessFunction implements Algorithm {
	private Control  control;
	private JTextArea textArea;
	private JPanel content = new JPanel();
//	public static void main(String[] args)
//	{
//	      JFrame newFrame = new JFrame("exampleWindow");
//	      ExampleFitnessFunction instance = new ExampleFitnessFunction();
//	      newFrame.setContentPane(instance.getAlgorithmPanel());
//	      newFrame.pack();
//	      newFrame.setVisible(true);
//	}
	public ExampleFitnessFunction(){
		content.setLayout(new BorderLayout());
		content.add(createParameterPanel(), BorderLayout.CENTER);
		JButton buttonRun = new JButton("Run");
		buttonRun.addActionListener(actionEvent -> run());
		content.add(buttonRun, BorderLayout.PAGE_END);
		content.setPreferredSize(new Dimension(300,300));
	}
	private void run() {
		
		float fitness = getFitnessValue();
		println("" + fitness);
	}
	private JPanel createParameterPanel() {
		JPanel parameterPanel = new JPanel();
		parameterPanel.setLayout(new BoxLayout(parameterPanel, BoxLayout.PAGE_AXIS));
		textArea = new JTextArea();
		textArea.setEditable(false);
		JScrollPane scrollPane = new JScrollPane(textArea);
		parameterPanel.add(scrollPane);
		return parameterPanel;
	}
	@Override
	public JPanel getAlgorithmPanel() {
		return content;
	}

	@Override
	public void setController(Control control) {
		this.control = control;
	}
	private void clear() {
		textArea.setText("");
	}
	private void print(String message) {
		textArea.append(message);
	}
	private void println(String message) {
		textArea.append(message + "\n");
	}
	
	private float getFitnessValue() {
		float overallFitness = 0f;
		//Calculate all timesteps
		for(int timestep = 0; timestep <100; timestep++) {
			control.calculateStateForTimeStep(timestep);
		}
		//Calculate all timesteps
		for(int timestep = 0; timestep <100; timestep++) {
			overallFitness += getFitnessValueForState(control.getSimManager().getDecorState(timestep));
		}
		return overallFitness;
	}

	private float getFitnessValueForState(DecoratedState state) {
		float fitnessOfTimestep = 0f;
		for(DecoratedNetwork net : state.getNetworkList()) {
			fitnessOfTimestep += net.getConsumerList().stream().map(con -> con.getState()).map(objectState -> StateToFloat(objectState)).reduce(0.0f, (a, b) -> (a + b));
			fitnessOfTimestep += net.getConsumerSelfSuppliedList().stream().map(con -> 1f).reduce(0.0f, (a, b) -> (a + b));
		}
		return fitnessOfTimestep;
	}
	private float StateToFloat(HolonObjectState state) {
		switch (state) {
		case NOT_SUPPLIED:
			return -5f;
		case NO_ENERGY:
			return 0f;
		case OVER_SUPPLIED:
			return -2f;
		case PARTIALLY_SUPPLIED:
			return -1f;
		case PRODUCER:
			return 0f;
		case SUPPLIED:
			return 1f;
		default:
			return 0f;
		}
	}
}
