package lt.ktu.gmj.tasks;

//import lt.ktu.gmj.tasks.*;

import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JTabbedPane;

import lt.ktu.gmj.Domain;
import lt.ktu.gmj.Point;
import lt.ktu.gmj.Task;
import defaultPackage.MeGraphics;

public class MePortfolio implements Task {
	private Domain domain = new Domain();

	int Iterations, InitialPoint, BankLength, ShareLength, InsuranceLength;

	JProgressBar wProgressBar;

	JLabel wALabel[];

	double AllBankrupt[], AllDividends[], x[], ObjectValue[], Uf[];

	double Resours;

	int InType;

	String mMethod;

	Thread Counter;

	Vector wItVector, wFVector;

	boolean SuspendStatus = false, StopStatus = false, FrameCreated = false;

	MeGraphics mGraphics;

	JTabbedPane wTabbedPane;

	JButton w1Button, w2Button;

	// ------------------------------
	double naud_f[][] = { { 0.0, 0.0, 0.0, 0.0, 0.0 },
			{ 0.5, 0.025, 0.125, 0.025, 0.0 },
			{ 0.675, 0.05, 0.25, 0.075, 0.0 }, { 0.775, 0.1, 0.375, 0.2, 0.0 },
			{ 0.85, 0.15, 0.5, 0.5, 0.0 }, { 0.9, 0.225, 0.625, 0.8, 0.0 },
			{ 0.95, 0.325, 0.75, 0.925, 0.0 },
			{ 0.975, 0.5, 0.875, 0.975, 0.0 }, { 1.0, 1.0, 1.0, 1.0, 1.0 } };

	// double yk[] = {0, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2.0};
	double yk[] = new double[9]; // = {0, 0.13, 0.26, 0.39, 0.52, 0.65, 0.78,

	// 0.91, 1.0};
	// ------------------------------

	int Risk = 3, it = 0, Length = 0;

	double SumMax = 0.0;

	public MePortfolio() {
	}

	public void setParameters(int Iterations[], int InType, double Resours,
			double AllBankrupt[], double AllDividends[],
			JProgressBar wProgressBar, JLabel wALabel[],
			JTabbedPane wTabbedPane, JButton w1Button, JButton w2Button,
			int BankLength, int ShareLength, int InsuranceLength,
			double ObjectValue[], String mMethod, double Uf[]) {
		this.Iterations = Iterations[0];
		this.InitialPoint = Iterations[1];
		this.InType = InType;
		this.Resours = Resours;
		this.AllBankrupt = AllBankrupt;
		this.AllDividends = AllDividends;
		this.wALabel = wALabel;
		this.wProgressBar = wProgressBar;
		this.wTabbedPane = wTabbedPane;
		this.w1Button = w1Button;
		this.w2Button = w2Button;
		this.BankLength = BankLength;
		this.ShareLength = ShareLength;
		this.InsuranceLength = InsuranceLength;
		this.ObjectValue = ObjectValue;
		this.mMethod = mMethod;
		this.Uf = Uf;
		if (InType == 0)
			Risk = 3; // Real
		else if (InType == 1)
			Risk = 0; // Prudent
		else if (InType == 2)
			Risk = 1; // Risk
		else if (InType == 3)
			Risk = 2; // Rich
		else if (InType == 4) {
			Risk = 4; // User
			for (int i = 0; i < 9; i++)
				naud_f[i][Risk] = Uf[i];
		}
		Length = AllDividends.length;
		SetYk();
	}

	void SetYk() {
		double max = 0.0;
		for (int i = 0; i < Length; i++)
			if (max < (AllDividends[i] - 1))
				max = AllDividends[i] - 1;
		max = max / 8;
		for (int i = 0; i < 9; i++)
			yk[i] = Round(i * max);
	}

	public Domain domain() {
		return domain;
	}

	public void CounterPoint(Thread Counter) {
		this.Counter = Counter;
	}

	/*- Function fi --------------------------------------------*/

	public double f(Point pt) {
		x = new double[Length];
		double viso = 0;
		// System.out.println("Length "+pt.x.length);
		for (int i = 0; i < Length; i++)
			viso += pt.x[i];
		if (viso == 0)
			return 0; // data can't be normalize
		if (viso > 1)
			for (int i = 0; i < Length; i++)
				x[i] = pt.x[i] / viso; // normalize
		else
			for (int i = 0; i < Length; i++)
				x[i] = pt.x[i];

		++it;
		double Sum = 0.0;
		int Power = (int) Math.pow(2, Length);
		// if ((AllOk(Risk) == Length) && (Zok() == InsuranceLength)) // Ar
		// tinka visi sugeneruoti x pagal zogaus naudingumo funkcija ir ar
		// draudimo z>=x
		if ((Zok() == InsuranceLength)) // Ar tinka visi sugeneruoti x pagal
			// zogaus naudingumo funkcija ir ar
			// draudimo z>=x
			for (int i = 0; i < Power; i++) // Deterministic metod (perrenkami
			// visi galimi dankrotai ir
			// islikimai)
			{
				double z = 0.0, P = 1.0;
				for (int j = 0; j < Length; j++) // z = for year
				{
					if ((i & (1 << (j))) != 0) {
						z += (AllDividends[j] - 1) * x[j];
						P *= AllBankrupt[j];
					} else {
						P *= 1 - AllBankrupt[j];
					}
				}
				int ji = 0;
				for (int k = 0; k < 8; k++)
					if (z >= yk[k])
						ji = ji + 1; // Nustato vieta naudingumo funkcijoje
				double Naud = 0.0;
				// System.out.println(" Z "+z+" AllDividends "+AllDividends[0]+"
				// 2 "+AllDividends[1]);
				Naud = (((naud_f[ji][Risk] - naud_f[ji - 1][Risk]) * (z - yk[ji - 1]))
						/ (yk[ji] - yk[ji - 1]) + naud_f[ji - 1][Risk]);
				// System.out.println("It "+it+" Z "+z+" Naud "+Naud+" P "+P);
				if (Risk == 0)
					Sum += Naud * P; // Prudent
				if (Risk == 1)
					Sum += Naud * P; // Risk
				if (Risk == 2)
					Sum += Naud * P; // Rich
				if (Risk == 3)
					Sum += Naud * P; // Real
				if (Risk == 4)
					Sum += Naud * P; // Real
				Sum = Round(Sum);
			}
		if (Sum > SumMax) {
			SumMax = Sum;
			// System.out.println("MAXSum "+SumMax);
			Write();
			wALabel[0].setText("" + it); // Iterations
			wALabel[Length + 2].setText("" + Round(SumMax)); // Iterations
			wItVector.addElement(new Integer(it));
			wFVector.addElement(new Double(SumMax));
			if (FrameCreated)
				mGraphics.repaint();
		}
		Wait(it); // Thrred Control
		return -1 * SumMax;
	}

	// -------- METODS -------------------------------------------
	// -------- METODS -------------------------------------------
	// -------- METODS -------------------------------------------

	double Round(double value) {
		long w = 100000000;
		return (double) Math.round(value * w) / w;
	}

	int AllOk(int Risk) {
		int Allok = 0;
		for (int i = 0; i < Length; i++) {
			int ji = 0;
			double z = x[i];
			for (int k = 0; k < 8; k++)
				if (z >= yk[k])
					ji = ji + 1;
			double Naud = ((naud_f[ji][Risk] - naud_f[ji - 1][Risk]) * (z - yk[ji - 1]))
					/ (yk[ji] - yk[ji - 1]) + naud_f[ji - 1][Risk];
			if ((AllBankrupt[i] >= Naud))
				Allok = Allok + 1;
		}
		return Allok;
	}

	int Zok() {
		if (InsuranceLength == 0)
			return 0;
		int Allok = 0, k;
		for (int i = 0; i < InsuranceLength; i++) {
			k = BankLength + ShareLength + i;
			if (ObjectValue[i] >= x[k] * AllDividends[k])
				Allok = Allok + 1;
		}
		return Allok;
	}

	// ----------------- Write To Screen -------------------
	void Write() {
		double Sum = 0;
		for (int j = 0; j < Length; j++) {
			double d = Math.round(AllDividends[j] * Resours * x[j] * 100);
			d = d / 100;
			Sum = Sum + d;
		}
		Sum = Math.round(Sum * 100);
		Sum = Sum / 100;
		wALabel[Length + 1].setText("" + Sum);
		for (int j = 0; j < Length; j++) // Write to screen
		{
			double d = Math.round(Resours * x[j] * 100);
			d = d / 100;
			wALabel[j + 1].setText("" + d);
		}
	}

	public void Data(Vector wItVector, Vector wFVector) {
		this.wItVector = wItVector;
		this.wFVector = wFVector;
	}

	public void FrameC(MeGraphics mGraphics) {
		this.mGraphics = mGraphics;
		FrameCreated = true;
	}

	public void FrameD() {
		FrameCreated = false;
	}

	// ------------------------------------------------

	void Wait(int i) {
		wProgressBar.setValue(i); // ProgresBar
		try {
			Thread.sleep(10); // Pause
		} catch (InterruptedException ie) {
		}
		;
		if (StopStatus) {
			Finished();
			Counter.stop();
		}
		if ((SuspendStatus) && (Iterations != i))
			Suspend();
	}

	// -----------------------------------------------------------------
	// -------------- Thread Control -----------------------------------

	void Finished() // Inside thread
	{
		wTabbedPane.setEnabledAt(0, true);
		if (InType == 4)
			wTabbedPane.setEnabledAt(1, true);
		wTabbedPane.setEnabledAt(2, true);
		wTabbedPane.setEnabledAt(3, true);
		wTabbedPane.setEnabledAt(4, true);
		w2Button.setEnabled(false);
		w2Button.setToolTipText(null);
		w1Button.setText("Start");
		w1Button.setToolTipText("Start investment count");
	}

	public void FinishedCounter() // Outside Thread
	{
		if (SuspendStatus) {
			Finished();
			Counter.stop();
		}
		StopStatus = true;
	}

	public void StartedCounter() {
		wTabbedPane.setEnabledAt(0, false);
		wTabbedPane.setEnabledAt(1, false);
		wTabbedPane.setEnabledAt(2, false);
		wTabbedPane.setEnabledAt(3, false);
		wTabbedPane.setEnabledAt(4, false);
		w1Button.setText("Pause");
		w1Button.setToolTipText("Pause investment count");
		w2Button.setEnabled(true);
		w2Button.setToolTipText("Stop investment count");
	}

	public void Suspend() {
		w1Button.setText("Continue");
		w1Button.setToolTipText("Continue investment count");
		Counter.suspend();
	}

	public void SuspendCounter() {
		SuspendStatus = true;
	}

	public void ResumeCounter() {
		SuspendStatus = false;
		w1Button.setText("Pause");
		w1Button.setToolTipText("Pause investment count");
		Counter.resume();
	}

}