package lt.ktu.gmj.analysis;

import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.util.Vector;
import lt.ktu.gmj.*;
import java.awt.event.*;
import lt.monarch.charts.*;
import java.net.*;

public class NashProfit extends ResultFrame implements ChartPointProvider{

	public double GetXMin(){
          if (profx.length<1) return 0;
          int i;
          double min=999999;
          for (i=0;i<profx.length;i++)
            	if (profx[i]<min) min=profx[i];
          return min;
	}

	public double GetXMax(){
          if (profx.length<1) return 1;
          int i;
          double max=-999999;
          for (i=0;i<profx.length;i++)
            	if (profx[i]>max) max=profx[i];
          return max;
	}

	public double GetYMin(){
	if (profy.length<1) return 0;
		int i;
		double min=999999;
		for (i=0;i<profy.length;i++)
		  	if (profy[i]<min) min=profy[i];
		return min;
	}

	public double GetYMax()	{
	if (profy.length<1) return 1;
		int i;
		double max=-999999;
		for (i=0;i<profy.length;i++) if (profy[i]>max) max=profy[i];
		return max;
	}

    // smooth using Wiener filter
    public void WienerFilter() {
		double b[] = new double[n];
		double c[] = new double[n];
		double r;
		double s;
		s=(new Double(st.getText())).doubleValue();
	
		double bb=1;	// (0.3)
		b[0]=1;		// (0.3)
		for (int i=1; i<n; i++){
			r=Math.abs(x_in[i]-x_in[i-1]);
			if (s==0) System.out.println("division by 0. (1)");
			b[i]=(s*b[i-1]+r*bb)/s;	// (0.5)
			bb=bb+b[i];	// (0.5)
		}

		double cc=0;
		c[n-1]=1;		// (0.6)
		for (int i=n-2;i>=0;i--){
			r=Math.abs(x_in[i]-x_in[i+1]);
			cc=cc+c[i+1];		// (0.7)
			if (s==0) System.out.println("division by 0. (2)");
			c[i]=(s*c[i+1]+r*cc)/s;
		}

		double sby, sb, scy, sc, tmp;
		for (int i=0;i<n;i++){
			sby=0; sb=0; scy=0; sc=0;
			for (int j=0;j<=i;j++){
				sby=sby+b[j]*y_in[j];
				sb=sb+b[j];
			}
			for (int j=i+1;j<n;j++)	{
				scy=scy+c[j]*y_in[j];
				sc=sc+c[j];
			}

			tmp=sb+b[i]*sc/c[i];
			if (tmp==0) System.out.println("division by 0. (3)");
			if (c[i]==0) System.out.println("division by 0. (4)");
			y_out[i]=(sby+b[i]*scy/c[i])/tmp;	// (0.2)

		}
    }

    public synchronized void WienerFilterCmd() {
		n=Math.min(profx.length,profy.length);
		y_in = new double[n];
		y_out = new double[n];
		x_in = new double[n];
	
		for (int i=0; i<n; i++) x_in[i]=profx[i];
		for (int i=0; i<n; i++) y_in[i]=profy[i];
		for (int i=0; i<n; i++) original_profy[i]=profy[i];
	
		WienerFilter();
	
		for (int i=0; i<n; i++) profy[i]=y_out[i];
	
		only_refresh=1;
		setupChart();
		only_refresh=0;
    }

    // smooth using low pass filter
    public void SmoothProfit() {
		for (int i=0; i<n; i++){
			double t1,t2,t3, nt2;
			t1=y_in[i]; t2=y_in[i]; t3=y_in[i];
			if (i-1>0) t1=y_in[i-1];
			if (i+1<n) t3=y_in[i+1];
			nt2=(t1+t2+t3)/3;
			y_out[i]=nt2;
		}
    }

    public synchronized void SmoothProfitCmd() {
		n=Math.min(profx.length,profy.length);
		y_in = new double[n];
		y_out = new double[n];
		x_in = new double[n];
	
		for (int i=0; i<n; i++) x_in[i]=profx[i];
		for (int i=0; i<n; i++) y_in[i]=profy[i];
		for (int i=0; i<n; i++) original_profy[i]=profy[i];
	
		SmoothProfit();
	
		for (int i=0; i<n; i++) profy[i]=y_out[i];
	
		only_refresh=1;
		setupChart();
		only_refresh=0;
    }

    public synchronized void Undo(){
		for (int i=0; i<original_profy.length; i++) profy[i]=original_profy[i];
		only_refresh=1;
		setupChart();
		only_refresh=0;
    }

    public NashProfit(){
      	super("Smooth and Wiener Filters");
          System.out.println("Analyser Walras Profit. ( Vytautas Perlibakas, 1999, Kaunas\n Modified By Povilas Treigys IN-9/2 VGTU Vilnius 2003\n Modified By Andrius Davidsonas VDU Kaunas 2005 )");
          only_refresh = 0;
          chart = new Chart();
          getContentPane().add("Center", chart);
          projectionChoice = new JComboBox();
          projectionChoice.addActionListener(new ActionListener(){
            	public void actionPerformed( ActionEvent e){
	              projection = projectionChoice.getSelectedIndex();
	              if (projection >-1) setupChart();
             	}
          });
          getContentPane().add("South", projectionChoice);
          JPanel panel = new JPanel();
          JPanel panel11 = new JPanel();
          JPanel panel12 = new JPanel();
          JPanel panel2 = new JPanel();
          panel.setLayout(new GridLayout(2, 1));
          panel11.setLayout(new GridLayout(1, 0, 0, 0));
          panel12.setLayout(new GridLayout(1, 0, 0, 0));
          panel2.setLayout(new GridLayout(10, 1));
          btn_smooth = new JButton("Smooth");
          btn_smooth.addActionListener(new ActionListener(){
          	 public void actionPerformed( ActionEvent e){
              	SmoothProfitCmd();
               }
          });          
          panel2.add("Center", btn_smooth);
          btn_wiener = new JButton("Wiener");
          btn_wiener.addActionListener(new ActionListener(){
          	public void actionPerformed( ActionEvent e) {
              	WienerFilterCmd();
              }
          });          
          panel2.add("Center", btn_wiener);
          btn_undo = new JButton("Undo");
          btn_undo.addActionListener(new ActionListener(){
          	public void actionPerformed( ActionEvent e){
              	Undo();
            	}
		});
          panel2.add("Center", btn_undo);
          btn_refresh = new JButton("Refresh");
          btn_refresh.addActionListener(new ActionListener(){
            	public void actionPerformed( ActionEvent e){
	              //AD modifications:
	              results.task().wienerDomain().calculatePoints();	//Skaiciuoja duomenis iskilumo testui
	              //Paima duomenis iskilumo testui
	              allX = results.task().wienerDomain().getX();
	              allY = results.task().wienerDomain().getY();	              
	              setupChart();
            	}
          });		
          panel2.add("Center", btn_refresh);
          diff = new JLabel("0");
          st = new JTextField("10", 6);
          panel11.add("North", new JLabel("F(x)="));
          panel11.add("North", diff);
          panel11.add("North", new JLabel("S="));
          panel11.add("North", st);
          //AD modifications:
          //URL url = HostNameRetriever.getApplet().getCodeBase();          
          //fileName = new JTextField(url.toString()+"test.txt", 50);   
          //fileName = new JTextField(HostNameRetriever.getCodeBase()+"test.txt", 50);               
          //btn_load = new JButton("Load");
          //btn_load.addActionListener(new ActionListener(){
          //	public void actionPerformed( ActionEvent e){
          //          loadCmd();
          //    }
          //});                   
          //panel12.add("North", fileName);
          //panel12.add("North", btn_load);
          panel.add("North", panel11);
          panel.add("North", panel12);
          getContentPane().add("North", panel);
          getContentPane().add("East", panel2);                
      }

    protected void loadCmd(){
      double temp;
      String st;
      int index, i =0;
      Vector tmp;
      boolean firstLine = true;
	//AD modifications:
      /*try{
      	URL tmyurl = new URL (fileName.getText());
      	URLConnection tmycon = tmyurl.openConnection();
      	BufferedReader raf = new BufferedReader(new InputStreamReader(tmycon.getInputStream()));
      	st = raf.readLine();
      	all = new Vector();
      	while (st != null){
        		i = 0;
        		while(st.length() >0){
        			if (firstLine){
        				tmp = new Vector();
           			all.add(tmp);
          		}
        			if ((i != 0) && (!firstLine)) dimensions[i-1] = new String("y"+i+"(x)");
        			index = st.indexOf(" ");
        			if (index == -1) index = st.length();
        			((Vector)all.elementAt(i)).addElement(Double.valueOf(st.substring(0,index)));
        			st = st.substring(index, st.length()).trim();
        			i++;
        		}
        		st = raf.readLine();
        		if (firstLine) dimensions = new String[i-1];
        		firstLine = false;
        }
        raf.close();
        projection = 0;
        projectionChoice.removeAllItems();
        for(i = 0; i < dimensions.length; i++) projectionChoice.addItem(dimensions[i]);
        setupChart();
	}catch (NumberFormatException e){
       System.out.println("NumberFormatException line 334");
     }catch (EOFException e){
       System.out.println("End of File line 338");
     }catch (IOException e){
       System.out.println("IO Exception line 342");
     }*/
    }

    protected synchronized void setupChart(){
        Vector seriesList = new Vector();
        MathAxisMapper yMapper = new MathAxisMapper();
        MathAxisMapper xMapper = new MathAxisMapper();
        XAxis axisX = new XAxis(xMapper);
        YAxis axisY = new YAxis(yMapper);
        series = new ConnectedSeries(this, axisX, axisY);
        Grid grid = new Grid(axisX, axisY);
		axisX.setLabel(dimensions[projection]);
		if (only_refresh==0){
			profx = new double[pointCount()];
			profy = new double[pointCount()];
			original_profy = new double[pointCount()];
			CalculateOutput(results);
		}
		cur_point_nr=0;

		double tmpymin, tmpymax;
		tmpymin = GetYMin();
		tmpymax = GetYMax();
		if (tmpymin==tmpymax)	{
			tmpymin=tmpymin-1;
			tmpymax=tmpymax+1;
		}
        yMapper.range.setRange(tmpymin,tmpymax);
        xMapper.range.setRange(GetXMin(), GetXMax());
        seriesList.addElement(series);
        axisX.prepare();
        axisY.prepare();

        chart.setup(seriesList);
        chart.setLeftAxis(axisY);
        chart.setXAxis(axisX);
        chart.setGrid(grid);
        chart.repaint();
    }

    public int pointCount(){
      if (all == null) return allX[0].length;
      else return ((Vector)all.elementAt(0)).size();
    }

	public void CalculateOutput(ResultRepository results){
                  if ((all != null) && ((Vector)all.elementAt(0)).size()>projection)
                  for (int i=0; i<((Vector)all.elementAt(0)).size(); i++){
                                 profx[i] = Double.parseDouble(((Vector)all.elementAt(0)).elementAt(i).toString());
                                 profy[i] = Double.parseDouble(((Vector)all.elementAt(projection+1)).elementAt(i).toString());
                  }else if (allY.length > projection){   
                  		profx = (double[])allX[projection].clone();
                       profy = (double[])allY[projection].clone();}
	}

    public ChartPoint point(int i){
		cur_point_nr=i;
		return pointFromResult(results.resultAt(0));
    }

    protected ChartPoint pointFromResult(Result r){
	double tmpx, tmpy;

	tmpx=profx[cur_point_nr];
	tmpy=profy[cur_point_nr];

        ChartPoint pt = new InvisibleDot(new Double(tmpx), new Double(tmpy));
        return pt;
    }

    public synchronized void newResult(ResultRepository results){
      Elevation wd =  results.task().wienerDomain();	
      if (wd != null) {
	      allX = wd.getX();
	      allY = wd.getY();
	      setupChart();
	  }	  
    }

    public void newProgressResult(ResultRepository results){
      Elevation wd =  results.task().wienerDomain();	
      if (wd != null) {
	      allX = wd.getX();
	      allY = wd.getY();
	      diff.setText(Double.toString(results.minValue()));
	      setupChart();
      }
  }

	public void finalResult(ResultRepository results){
		newProgressResult(results);
	}

	public synchronized void prepare(ResultRepository results)	{		
		super.prepare(results);
                Elevation wd =  results.task().wienerDomain();
                dimensions = wd.dimensions();
                int dim =  dimensions.length;
                dimensions = wd.dimensions();              
                allX = wd.getX();
                allY = wd.getY();
                projection = 1;
                projectionChoice.removeAllItems();
                for(int i = 0; i < dimensions.length; i++) projectionChoice.addItem(dimensions[i]);
                setupChart();
                diff.setText(Double.toString(results.minValue()));
		setupChart(); results.addObserver(this); show();
	}

	public synchronized void newLog(ResultRepository results)
	{
		chart.repaint();
	}
public JButton btn_smooth;
public JButton btn_wiener;
public JButton btn_undo;
public JButton btn_refresh;
public JButton btn_browse;
//public JButton btn_load;
public double y_in[];
public double x_in[];
public double y_out[];
public int only_refresh;
public int cur_point_nr;
public int n;
public double profx[];
public double profy[];
public double allX[][];
public double allY[][];
public double original_profy[];
public String dimensions[];
public JTextField st;
//public JTextField fileName;
public JLabel diff;
private static final String CMD_SMOOTH = "Smooth";
private static final String CMD_WIENER = "Wiener";
private static final String CMD_UNDO = "Undo";
private static final String CMD_REFRESH = "Refresh";
private static final String CMD_LOAD = "Load";
protected Chart chart;
protected int projection = 0;
protected ChartPointSeries series;
protected JComboBox projectionChoice;
private File f = null;
Vector all = null;
}

