package lt.ktu.gmj.analysis;

import javax.swing.*;
import java.awt.*;
import java.util.Vector;
import lt.ktu.gmj.*;
import lt.ktu.gmj.tasks.WalrasModel;
import java.awt.event.*;
import lt.monarch.charts.*;
public class WalrasProfit extends ResultFrame
    implements ChartPointProvider
{

	public int GetDomN(int projection)
	{
		if (projection==0) return 1;
		if (projection==1) return 4;
		if (projection==2) return 2;
		if (projection==3) return 5;
		System.out.println("ERROR: GetDomN");
		return 0;
	}

	public double GetXMin(int projection)
	{
		if (projection==0) return getWalrasModel().domain().min[2];
		if (projection==1) return getWalrasModel().domain().min[3];
		if (projection==2) return getWalrasModel().domain().min[0];
		if (projection==3) return getWalrasModel().domain().min[1];
		return 0;
	}

	public double GetXMax(int projection)
	{
		if (projection==0) return getWalrasModel().domain().max[2];
		if (projection==1) return getWalrasModel().domain().max[3];
		if (projection==2) return getWalrasModel().domain().max[0];
		if (projection==3) return getWalrasModel().domain().max[1];
		return 0;
	}

	public double GetXStep(int projection)
	{
          if (projection==0) return (getWalrasModel().domain().max[2] - getWalrasModel().domain().min[2]) / (100 / getWalrasModel().Precision);
          if (projection==1) return (getWalrasModel().domain().max[3] - getWalrasModel().domain().min[3]) / (100 / getWalrasModel().Precision);
          if (projection==2) return (getWalrasModel().domain().max[0] - getWalrasModel().domain().min[0]) / (100 / getWalrasModel().Precision);
          if (projection==3) return (getWalrasModel().domain().max[1] - getWalrasModel().domain().min[1]) / (100 / getWalrasModel().Precision);
          return 0;

	}



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 WalrasProfit()
    {
      super("Server Profit");
          System.out.println("Analyser Walras Profit. ( Vytautas Perlibakas, 1999, Kaunas\n Modified By Povilas Treigys EISm-3 VGTU Vilnius 2004 )");
          setWalrasModel(WalrasModel.getWalrasModel());
          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();
              setupChart();
                              }
                      });
          getContentPane().add("South", projectionChoice);
          JPanel panel = new JPanel();
          JPanel panel11 = new JPanel();
          JPanel panel12 = new JPanel();
          JPanel panel13 = new JPanel();
          JPanel panel2 = new JPanel();
          panel.setLayout(new GridLayout(3, 1));
          panel11.setLayout(new GridLayout(1, 0, 0, 0));
          panel12.setLayout(new GridLayout(1, 0, 0, 0));
          panel13.setLayout(new GridLayout(1, 0, 0, 0));
          panel2.setLayout(new GridLayout(10, 1));
          panel.add("North", panel11);
          panel.add("North", panel12);
          panel.add("North", panel13);
          btn_smooth = new JButton("Smooth");
          btn_smooth.addActionListener(new ActionListener(){
            public void actionPerformed( ActionEvent e)
                              {
              SmoothProfitCmd();
                              }
                      });
          panel2.add("North", btn_smooth);
          btn_wiener = new JButton("Wiener");
          btn_wiener.addActionListener(new ActionListener(){
            public void actionPerformed( ActionEvent e)
                              {
              WienerFilterCmd();
                              }
                      });
          panel2.add("North", btn_wiener);
          btn_undo = new JButton("Undo");
          btn_undo.addActionListener(new ActionListener(){
            public void actionPerformed( ActionEvent e)
                              {
              Undo();
            }
                      });
          panel2.add("North", btn_undo);
          btn_refresh = new JButton("Refresh");
          btn_refresh.addActionListener(new ActionListener(){
            public void actionPerformed( ActionEvent e)
                              {
              setupChart();
            }
                      });
          panel2.add("North", btn_refresh);
          diff = new JLabel("0");
          profit1 = new JLabel("0");
          profit2 = new JLabel("0");
          bestY1 = new JLabel("0");
          bestP1 = new JLabel("0");
          bestY2 = new JLabel("0");
          bestP2 = new JLabel("0");
          st = new JTextField("10", 6);
          diff.setText(Double.toString(getWalrasModel().bestf));
          profit1.setText(Double.toString(getWalrasModel().bestu1));
          profit2.setText(Double.toString(getWalrasModel().bestu2));
          bestY1.setText(Double.toString(getWalrasModel().bestY1));
          bestP1.setText(Double.toString(getWalrasModel().bestP1));
          bestY2.setText(Double.toString(getWalrasModel().bestY2));
          bestP2.setText(Double.toString(getWalrasModel().bestP2));
          panel11.add("North", new JLabel("F(x) difference = "));
          panel11.add("North", diff);
          panel11.add("North", new JLabel("Smoothing = "));
          panel11.add("North", st);
          panel12.add("North", new JLabel("1 - st server profit = "));
          panel12.add("North", profit1);
          panel12.add("North", new JLabel("2 - nd server profit = "));
          panel12.add("North", profit2);
          panel13.add("North", new JLabel("Y_1 = "));
          panel13.add("North", bestY1);
          panel13.add("North", new JLabel("P_1 = "));
          panel13.add("North", bestP1);
          panel13.add("North", new JLabel("Y_2 = "));
          panel13.add("North", bestY2);
          panel13.add("North", new JLabel("P_2 = "));
          panel13.add("North", bestP2);
          getContentPane().add("North", panel);
          getContentPane().add("East", panel2);

    }

    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);

	String ylabel[] = { "U1", "U2" };
        axisY.setLabel(ylabel[projection%2]);
	String xlabel[] = { "Y_1", "Y_2", "P_1", "P_2" };
        axisX.setLabel(xlabel[projection]);

	if (only_refresh==0)
	{
		profx = new double[PointCnt()];
		profy = new double[PointCnt()];
		original_profy = new double[PointCnt()];
		CalculateOutput();
	}

	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(projection), GetXMax(projection));
        seriesList.addElement(series);
        axisX.prepare();
        axisY.prepare();

        chart.setup(seriesList);
        chart.setLeftAxis(axisY);
        chart.setXAxis(axisX);
        chart.setGrid(grid);
        chart.repaint();
    }

	public int PointCnt()
	{
		getWalrasModel().pointnum[0]=(int)(100 / getWalrasModel().Precision )+1;
		getWalrasModel().pointnum[1]=(int)(100 / getWalrasModel().Precision )+1;
		return getWalrasModel().pointnum[projection];
	}

    public int pointCount()
    {
 	return Math.min(profx.length,profy.length);
    }


	public void CalculateOutput()
	{
		double ptx[];
		ptx = new double[8];
       ptx[0] = getWalrasModel().bestX11;
       ptx[1] = getWalrasModel().bestY1;
       ptx[2] = getWalrasModel().bestP1;
       ptx[3] = getWalrasModel().bestX22;
       ptx[4] = getWalrasModel().bestY2;
       ptx[5] = getWalrasModel().bestP2;
       ptx[6] = getWalrasModel().bestX12;
       ptx[7] = getWalrasModel().bestX21;

		int j=0;
		for (double i=GetXMin(projection); i<=GetXMax(projection); i+=GetXStep(projection))
		{
			ptx[GetDomN(projection)]=i;
			getWalrasModel().ProcessServers(ptx[0],ptx[1],ptx[2],ptx[3],ptx[4],ptx[5],ptx[6],ptx[7]);
			profy[j] = getWalrasModel().getServerProfit(projection%2);
			profx[j] = i;
			j=j+1;
		}

	}


    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 n)
    {
      curriter.setText(Integer.toString(getWalrasModel().curriter));
    }

    public void newProgressResult(ResultRepository n)
    {
      diff.setText(Double.toString(getWalrasModel().bestf));
      profit1.setText(Double.toString(getWalrasModel().bestu1));
      profit2.setText(Double.toString(getWalrasModel().bestu2));
      bestY1.setText(Double.toString(getWalrasModel().bestY1));
      bestP1.setText(Double.toString(getWalrasModel().bestP1));
      bestY2.setText(Double.toString(getWalrasModel().bestY2));
      bestP2.setText(Double.toString(getWalrasModel().bestP2));
      setupChart();

  }

	public void finalResult(ResultRepository n)
	{
		newProgressResult(n);
	}

	public synchronized void prepare(ResultRepository n)
	{
		super.prepare(n);

		String dim[] =
		{
		 "1-st server profit (y1)",
		 "2-nd server profit (y2)",
		 "1-st server profit (p1)",
		 "2-nd server profit (p2)"
		};

		for(int i = 0; i < dim.length; i++) projectionChoice.addItem(dim[i]);
		setupChart(); results.addObserver(this); show();
	}

	public synchronized void newLog(ResultRepository n)
	{
		chart.repaint();
	}

    public boolean action(Event evt, Object arg)
    {
	if(evt.target == projectionChoice)
	{
		projection = projectionChoice.getSelectedIndex();
		setupChart();
	}
	if (evt.target == btn_smooth)
	{ SmoothProfitCmd();
	}
        if (evt.target == btn_wiener)
	{ WienerFilterCmd();
	}
        if (evt.target == btn_undo)
	{ Undo();
	}
        if (evt.target == btn_refresh)
	{ setupChart();
	}

	return false;
    }
    private WalrasModel getWalrasModel()
        {
            return gWalrasModel;
        }

        private void setWalrasModel(WalrasModel igWalrasModel)
        {
            gWalrasModel = igWalrasModel;
        }

public JButton btn_smooth;
public JButton btn_wiener;
public JButton btn_undo;
public JButton btn_refresh;
public double y_in[];
public double x_in[];
public double y_out[];
public int n;
public int only_refresh;
public int cur_point_nr;
public double profx[];
public double profy[];
public double original_profy[];
public JTextField st;
public JLabel control1;
public JLabel control2;
public JLabel clserved1;
public JLabel clserved2;
public JLabel clgone;
public JLabel bestiter;
public JLabel curriter;
public JLabel diff;
public JLabel profit1;
public JLabel profit2;
public JLabel v1;
public JLabel v2;
public JLabel bestX11;
public JLabel bestY1;
public JLabel bestP1;
public JLabel bestX22;
public JLabel bestY2;
public JLabel bestP2;
public JLabel bestX12;
public JLabel bestX21;
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";
protected Chart chart;
protected int projection;
protected ChartPointSeries series;
protected JComboBox projectionChoice;
private WalrasModel gWalrasModel;

}

