package Division;

import Division.gui.DisplayDivision;

import javax.swing.*;
import java.util.Collections;
import java.util.List;
import java.awt.event.ActionListener;
import java.awt.*;

public class TalmudDivision implements DivisionCalculator{

	public void calculateShare(List<Claimer> claimers, double money, ActionListener finish) {
		// first sort the players
		Collections.sort(claimers, new ClaimerComparator());
		
		// sum the total amount of claims
		double totalClaim = 0;
		for(Claimer p : claimers){
			totalClaim += p.getClaimed();
		}
		
		// fill the bottom half of the vessels
		fillBottom(claimers, totalClaim, money);
		
		// if we got more money then the bottom half of the vessels can indicate, also fill the top ones
		if(money > totalClaim / 2){
			fillTop(claimers, totalClaim, money);
		}
        System.out.println("Payout: ");
        for (Claimer c:claimers)
            System.out.println("  Claim: "+c.getClaimed()+"   Received: "+c.getReceived());
        new DisplayDivision(claimers, true, getDescriptor()); 

        finish.actionPerformed(null);
	}
	
	/**
	 * Fill the bottom half of the vessels
	 * @param claimers the persons who have claims
	 * @param totalClaim the total claimed money (the same as the sum of the claims of the claimers)
	 * @param money the money to divide among the claims
	 */
	private void fillBottom(List<Claimer> claimers, double totalClaim, double money){
		// we need more then just the bottom vessels for dividing the money
		if(money >= totalClaim / 2){
			for(Claimer p : claimers){
				p.setReceived(p.getClaimed() / 2);
			}
			return;
		}
		
		double Z = money; // the money left
		int N = claimers.size();
		int i,j;
		double amountLeft;
		
		for(i = 0; i < N; i++){
			// check how much more can be put in this vessel
			amountLeft = claimers.get(i).getClaimed() / 2;
			if(i > 0){
				amountLeft -= claimers.get(i - 1).getClaimed() / 2;
			}
			
			// check if we can top this vessel up
			if( (amountLeft * (N - i)) < Z){
				// top it up
				for(j = i; j < N; j++){
					claimers.get(j).addToReceived(amountLeft);
				}
				Z -= (amountLeft * (N-i));
			}
			else{
				// divide the remaining money equally over the remaining vessels
				for(j = i; j < N; j++){
					claimers.get(j).addToReceived(Z / (N - i));
				}
				Z = 0;
			}
		}
	}
	
	/**
	 * Fill the top of the vessels if possible
	 * @param claimers the people who have claims
	 * @param totalClaim the total claimed money (the same as the sum of the claims of the players)
	 * @param money the money to divide among the claims
	 */
	private void fillTop(List<Claimer> claimers, double totalClaim, double money){
		// check if the money is greater or equal to the claims then again add half, so every player gets what he claimed
		if(money >= totalClaim){
			for(Claimer p : claimers){
				p.addToReceived(p.getClaimed() / 2);
			}
			return;
		}
		
		double Z = money - totalClaim / 2; // the money still left to divide
		int N = claimers.size();
		int i, j;
		double a; // temporary amount
		
		// we go from right to left, that is from the most claiming person to the less claiming person or until the money has run out
		for(i = N - 1; i >= 0 && Z > 0; i--){ 
			a = claimers.get(i).getClaimed() / 2;
			if(i > 0){
				a -= claimers.get(i - 1).getClaimed() / 2;
			}
			
			if(a * (N - i) <= Z){
				for(j = i; j < N; j++){
					claimers.get(j).addToReceived(a);
				}
				Z -= a * (N - i);
			}
			else{
				for(j = i; j < N; j++){
					claimers.get(j).addToReceived(Z / (N - i));
				}
				Z = 0;
			}
		}
	}

    public String getDescriptor() {
        return "Talmud division";
    }

    public void stop() {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    public void settings(ActionListener updater) {
        final JFrame settingsFrame=new JFrame("Dominated Actions settings");
        settingsFrame.setLayout(new GridBagLayout());
        GridBagConstraints cons=new GridBagConstraints();
        cons.weightx=0.5;
        cons.weighty=0.5;
        cons.gridx=0;
        cons.gridy=0;
        cons.gridheight=1;
        cons.gridwidth=1;
        cons.fill=GridBagConstraints.HORIZONTAL;
        JPanel aboutPanel=new JPanel();
        aboutPanel.setBorder(BorderFactory.createCompoundBorder(
                        BorderFactory.createTitledBorder("About"),
                        BorderFactory.createEmptyBorder(5,5,5,5)));
            aboutPanel.setLayout(new GridLayout(1,1));
            JTextArea about=new JTextArea();
            about.setEditable(false);
            about.setCursor(null);
            about.setOpaque(false);
            about.setFocusable(false);
            about.setLineWrap(true);
            about.setText("Determines payoff by the Talmud rule and shows them by means of communicating vessels.");
            aboutPanel.add(about);
        settingsFrame.add(aboutPanel,cons);

        settingsFrame.setSize(300,200);
        settingsFrame.setVisible(true);
    }}
