package unileipzig.isys.neuronviz.kernel;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SpringLayout;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import unileipzig.isys.neuronviz.streamer.FileInputStreamer;
import unileipzig.isys.neuronviz.streamer.StandardInputStreamer;

public class StreamController extends JPanel implements ActionListener, ChangeListener, ParseListener
{
    private DataStreamer dataStreamer;
    private String libDir;
    private int streamingSpeed = 150;
	
    private JButton startNStopStreaming, nextStreamingStep, prevStreamingStep;
    private JSlider streamPosition;
    private JSpinner speedControl, intervallControll;

    private boolean sliderAltered = false;
	
	
    public StreamController(DataStreamer streamer, String libDir)
    {
	this.dataStreamer = streamer;
	this.libDir = libDir;
	System.err.println(libDir);
						
	if(dataStreamer.getStreamingMode() == DataStreamer.FILE_MODE)
	    {
		setLayout(new BorderLayout());
			
		Border empty = BorderFactory.createEmptyBorder(5, 5 , 5 , 5);
		TitledBorder title = BorderFactory.createTitledBorder("Streaming Control");
			
		Border compound = BorderFactory.createCompoundBorder(title, empty);
		setBorder(compound);
			
		// create speed control spinner
		speedControl = new JSpinner();
		SpinnerModel model = new SpinnerNumberModel(95, 1, 100, 1);		
		speedControl.setModel(model);
		speedControl.addChangeListener(this);

		// describing label
		JLabel spinnerLabel = new JLabel(" Streaming Speed in percent");

		// put everyting together in a panel and then add it to the main panel
		JPanel spinnerPanel = new JPanel();
		spinnerPanel.setLayout(new FlowLayout());
		spinnerPanel.add(speedControl);
		spinnerPanel.add(spinnerLabel);

		add (BorderLayout.NORTH, spinnerPanel);
			
			
		JPanel southPanel = new JPanel();
		southPanel.setLayout(new BorderLayout());
			
		// create and add a slider to jump to special positions
		streamPosition = new JSlider(JSlider.HORIZONTAL, 0, 1000, 0);
		streamPosition.setMajorTickSpacing(100);
		streamPosition.setMinorTickSpacing(20);
		streamPosition.setPaintTicks(true);
		streamPosition.setPaintLabels(false);
		streamPosition.setEnabled(false);
		streamPosition.addChangeListener(this);

		southPanel.add(BorderLayout.NORTH, streamPosition);

		JPanel southSouthPanel = new JPanel();
		southSouthPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
			
		// create and add a start/stop button
		startNStopStreaming = new JButton();
		startNStopStreaming.setIcon(new ImageIcon(libDir +"/b_play.png"));
		startNStopStreaming.setActionCommand("start_streaming");
		startNStopStreaming.addActionListener(this);
			
		// create the next/prev buttons
		nextStreamingStep = new JButton();
		nextStreamingStep.setIcon(new ImageIcon(libDir +"/b_next.png"));
		nextStreamingStep.setActionCommand("next_step");
		nextStreamingStep.addActionListener(this);
			
		prevStreamingStep = new JButton();
		prevStreamingStep.setIcon(new ImageIcon(libDir +"/b_prev.png"));
		prevStreamingStep.setActionCommand("prev_step");
		prevStreamingStep.addActionListener(this);

		southSouthPanel.add(prevStreamingStep);
		southSouthPanel.add(startNStopStreaming);
		southSouthPanel.add(nextStreamingStep);
			
						
		southPanel.add(BorderLayout.SOUTH, southSouthPanel);
			
		add(BorderLayout.SOUTH, southPanel);
	    }
	else if (dataStreamer.getStreamingMode() == DataStreamer.PIPE_MODE)
	    {
		setLayout(new BorderLayout());
			
		// create speed control spinner
		intervallControll = new JSpinner();
		SpinnerModel model = new SpinnerNumberModel(1, 1, 100, 1);		
		intervallControll.setModel(model);
		intervallControll.addChangeListener(this);

		// describing label
		JLabel spinnerLabel = new JLabel(" Redraw intervall of the net");

		// put everyting together in a panel and then add it to the main panel
		JPanel spinnerPanel = new JPanel();
		spinnerPanel.setLayout(new FlowLayout());
		spinnerPanel.add(intervallControll);
		spinnerPanel.add(spinnerLabel);

		add (BorderLayout.NORTH, spinnerPanel);
	    }
    }

    public void actionPerformed(ActionEvent e)
    {
	if(e.getActionCommand().equals("start_streaming"))
	    {
		startNStopStreaming.setActionCommand("stop_streaming");
		startNStopStreaming.setIcon(new ImageIcon(libDir +"/b_stop.png"));
		//startNStopStreaming.setText("Stop streaming");
		dataStreamer.startStreaming(streamingSpeed);
			
		streamPosition.setEnabled(false);
	    }
	else if(e.getActionCommand().equals("stop_streaming"))
	    {
		startNStopStreaming.setActionCommand("start_streaming");
		startNStopStreaming.setIcon(new ImageIcon(libDir +"/b_play.png"));
		//startNStopStreaming.setText("Start streaming");
		dataStreamer.stopStreaming();

		streamPosition.setEnabled(true);
	    }
	else if(e.getActionCommand().equals("next_step"))
	    {
		dataStreamer.readDataLine();

		double lineNum = ((FileInputStreamer)(dataStreamer)).getLineNum();
		double eod = dataStreamer.getEndOfDescription();
		double actLine = dataStreamer.getActualLine();
		double step = (double) ((double)streamPosition.getMaximum()/(lineNum-eod));
			
		sliderAltered = true;
		if(actLine-eod > 0)
		    streamPosition.setValue((int)((actLine-eod)*step));

		if(streamPosition.getValue() >= streamPosition.getMaximum())
		    {
			startNStopStreaming.setActionCommand("start_streaming");
			startNStopStreaming.setIcon(new ImageIcon(libDir +"/b_play.png"));
			//startNStopStreaming.setText("Start streaming");
			dataStreamer.stopStreaming();

			streamPosition.setEnabled(true);
		    }
	    }
	else if(e.getActionCommand().equals("prev_step"))
	    {
		((FileInputStreamer)(dataStreamer)).gotoDataLine(dataStreamer.getActualLine()-1);

		double lineNum = ((FileInputStreamer)(dataStreamer)).getLineNum();
		double eod = dataStreamer.getEndOfDescription();
		double actLine = dataStreamer.getActualLine();
		double step = (double) ((double)streamPosition.getMaximum()/(lineNum-eod));
			
		sliderAltered = true;
		if(actLine-eod > 0)
		    streamPosition.setValue((int)((actLine-eod)*step));

		if(streamPosition.getValue() >= streamPosition.getMaximum())
		    {
			startNStopStreaming.setActionCommand("start_streaming");
			startNStopStreaming.setIcon(new ImageIcon(libDir +"/b_play.png"));
			//startNStopStreaming.setText("Start streaming");
			dataStreamer.stopStreaming();

			streamPosition.setEnabled(true);
		    }
	    }
    }

    public void stateChanged(ChangeEvent e)
    {
	if (e.getSource() == streamPosition && !streamPosition.getValueIsAdjusting())
	    {
		if(startNStopStreaming.getActionCommand().equals("start_streaming") && !sliderAltered)
		    {
			int position = streamPosition.getValue();
			double lineNum = ((FileInputStreamer)(dataStreamer)).getLineNum();
			double eod = dataStreamer.getEndOfDescription();
			double actLine = dataStreamer.getActualLine();
			double step = (double) ((lineNum-eod)/(double)streamPosition.getMaximum());
				
			((FileInputStreamer)(dataStreamer)).gotoDataLine((int)(position * step - 1));
		    }
		sliderAltered = false;
	    }
	else if (e.getSource() == speedControl)
	    {
		streamingSpeed = 3000 - (30 * ((Integer)(speedControl.getValue())).intValue());
		dataStreamer.setThreadPause(streamingSpeed);
	    }
	else if (e.getSource() == intervallControll)
	    {
		int value = ((Integer)(intervallControll.getValue())).intValue();
		((StandardInputStreamer)(dataStreamer)).setNotifyIntervall(value);
	    }
			
    }

    public void createNeuralNet(ParseEvent e)
    {
    }

    public void createLayer(ParseEvent e)
    {
    }

    public void createNeuron(ParseEvent e)
    {
    }

    public void createConnection(ParseEvent e)
    {
    }

    public void descriptionTerminated(ParseEvent e)
    {
    }

    public void unknownCommand(ParseEvent e)
    {
    }

    public void channelReceived(ParseEvent e)
    {
	if (dataStreamer.getStreamingMode() != DataStreamer.FILE_MODE) return;
		
	if(startNStopStreaming.getActionCommand().equals("stop_streaming"))
	    {
		double lineNum = ((FileInputStreamer)(dataStreamer)).getLineNum();
		double eod = dataStreamer.getEndOfDescription();
		double actLine = dataStreamer.getActualLine();
		double step = (double) ((double)streamPosition.getMaximum()/(lineNum-eod));
			
		if(actLine-eod > 0)
		    streamPosition.setValue((int)((actLine-eod)*step));

		if(streamPosition.getValue() >= streamPosition.getMaximum())
		    {
			startNStopStreaming.setActionCommand("start_streaming");
			startNStopStreaming.setIcon(new ImageIcon(libDir +"/b_play.png"));
			//				startNStopStreaming.setText("Start streaming");
			dataStreamer.stopStreaming();

			streamPosition.setEnabled(true);
		    }
	    }
    }

    public void quitReceived(ParseEvent e)
    {
    }


}
