package gui.assets;

import gui.BalanceRenderer;
import gui.models.BalancesComboBoxModel;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;
import javax.swing.border.EmptyBorder;

import org.mapdb.Fun.Tuple2;

import controller.Controller;
import database.SortableList;
import qora.account.Account;
import qora.assets.Asset;
import qora.payment.Payment;
import utils.Pair;

@SuppressWarnings("serial")
public class PayDividendFrame extends JFrame
{
	private Asset asset;
	private JTextField txtAsset;
	private JTextField txtAccount;
	private JComboBox<Pair<Tuple2<String, Long>, BigDecimal>> cbxAssetToPay;
	private JTextField txtAmount;
	private JTextField txtHolders;
	private JButton generateButton;

	public PayDividendFrame(Asset asset)
	{
		super("Qora - Pay Dividend");
		
		this.asset = asset;
		
		//CLOSE
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		
		//ICON
		List<Image> icons = new ArrayList<Image>();
		icons.add(Toolkit.getDefaultToolkit().getImage("images/icons/icon16.png"));
		icons.add(Toolkit.getDefaultToolkit().getImage("images/icons/icon32.png"));
		icons.add(Toolkit.getDefaultToolkit().getImage("images/icons/icon64.png"));
		icons.add(Toolkit.getDefaultToolkit().getImage("images/icons/icon128.png"));
		this.setIconImages(icons);
		
		//LAYOUT
		this.setLayout(new GridBagLayout());
		
		//PADDING
		((JComponent) this.getContentPane()).setBorder(new EmptyBorder(5, 5, 5, 5));
		
		//LABEL GBC
		GridBagConstraints labelGBC = new GridBagConstraints();
		labelGBC.insets = new Insets(5,5,5,5);
		labelGBC.fill = GridBagConstraints.HORIZONTAL;   
		labelGBC.anchor = GridBagConstraints.NORTHWEST;
		labelGBC.weightx = 0;	
		labelGBC.gridx = 0;
		
		//COMBOBOX GBC
		GridBagConstraints cbxGBC = new GridBagConstraints();
		cbxGBC.insets = new Insets(5,5,5,5);
		cbxGBC.fill = GridBagConstraints.NONE;  
		cbxGBC.anchor = GridBagConstraints.NORTHWEST;
		cbxGBC.weightx = 0;	
		cbxGBC.gridx = 1;	
		
		//TEXTFIELD GBC
		GridBagConstraints txtGBC = new GridBagConstraints();
		txtGBC.insets = new Insets(5,5,5,5);
		txtGBC.fill = GridBagConstraints.HORIZONTAL;  
		txtGBC.anchor = GridBagConstraints.NORTHWEST;
		txtGBC.weightx = 1;	
		txtGBC.gridwidth = 2;
		txtGBC.gridx = 1;		
		
		//BUTTON GBC
		GridBagConstraints buttonGBC = new GridBagConstraints();
		buttonGBC.insets = new Insets(5,5,5,5);
		buttonGBC.fill = GridBagConstraints.NONE;  
		buttonGBC.anchor = GridBagConstraints.NORTHWEST;
		buttonGBC.gridwidth = 2;
		buttonGBC.gridx = 0;		
		
		//LABEL ASSET
		labelGBC.gridy = 0;
		JLabel assetLabel = new JLabel("Asset:");
		this.add(assetLabel, labelGBC);
		
		//TXT ASSET
		txtGBC.gridy = 0;
		this.txtAsset = new JTextField(asset.toString());
		this.txtAsset.setEditable(false);
        this.add(this.txtAsset, txtGBC);
        
        //LABEL ACCOUNT
      	labelGBC.gridy = 1;
      	JLabel accountLabel = new JLabel("Account:");
      	this.add(accountLabel, labelGBC);
      		
      	//TXT ACCOUNT
      	txtGBC.gridy = 1;
      	this.txtAccount = new JTextField(asset.getOwner().getAddress());
      	this.txtAccount.setEditable(false);
        this.add(this.txtAccount, txtGBC);
        
        //LABEL ASSET TO PAY
      	labelGBC.gridy = 2;
      	JLabel AssetToPayLabel = new JLabel("Asset to pay:");
      	this.add(AssetToPayLabel, labelGBC);
      		
      	//CBX ASSET TO PAY
      	txtGBC.gridy = 2;
      	this.cbxAssetToPay = new JComboBox<Pair<Tuple2<String, Long>, BigDecimal>>(new BalancesComboBoxModel(asset.getOwner()));
      	this.cbxAssetToPay.setRenderer(new BalanceRenderer());
        this.add(this.cbxAssetToPay, txtGBC);
      	
      	//LABEL AMOUNT
      	labelGBC.gridy = 3;
      	JLabel amountLabel = new JLabel("Amount to pay:");
      	this.add(amountLabel, labelGBC);
      		
      	//TXT AMOUNT
      	txtGBC.gridy = 3;
      	this.txtAmount = new JTextField();
      	this.txtAmount.setText("1");
        this.add(this.txtAmount, txtGBC);
        
      	//LABEL HOLDERS TO PAY
      	labelGBC.gridy = 4;
      	JLabel holdersToPayLabel = new JLabel("Holders to pay (1-400):");
      	this.add(holdersToPayLabel, labelGBC);
      		
      	//TXT QUANTITY
      	txtGBC.gridy = 4;
      	this.txtHolders = new JTextField();
      	this.txtHolders.setText("1");
        this.add(this.txtHolders, txtGBC);
		           
        //BUTTON GENERATE
        buttonGBC.gridy = 5;
        this.generateButton = new JButton("Generate Payment");
        this.generateButton.setPreferredSize(new Dimension(160, 25));
        this.generateButton.addActionListener(new ActionListener()
		{
		    public void actionPerformed(ActionEvent e)
		    {
		        onGenerateClick();
		    }
		});
    	this.add(this.generateButton, buttonGBC);
        
        //PACK
		this.pack();
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
	}
	
	@SuppressWarnings("unchecked")
	public void onGenerateClick()
	{
		int parsing = 0;
		try
		{
			//HOLDERS TO PAY
			parsing = 1;
			int holders = Integer.parseInt(this.txtHolders.getText());
			
			//AMOUNT TO PAY
			parsing = 2;
			BigDecimal amount = new BigDecimal(txtAmount.getText()).setScale(8);
			
			//ASSET TO PAY
			long assetKey = ((Pair<Tuple2<String, Long>, BigDecimal>) this.cbxAssetToPay.getSelectedItem()).getA().b;
			Asset assetToPay = Controller.getInstance().getAsset(assetKey);
			
			//BALANCES
			SortableList<Tuple2<String, Long>, BigDecimal> balances = Controller.getInstance().getBalances(this.asset.getKey());
			
			//GET ACCOUNTS AND THEIR TOTAL BALANCE
			List<Account> accounts = new ArrayList<Account>();
			BigDecimal total = BigDecimal.ZERO.setScale(8);
			for(int i=0; i<holders && i<balances.size(); i++)
			{
				Account account = new Account(balances.get(i).getA().a);
				accounts.add(account);
				
				total = total.add(balances.get(i).getB());
			}
			
			//CREATE PAYMENTS
			List<Payment> payments = new ArrayList<Payment>();
			for(Account account: accounts)
			{
				//CALCULATE PERCENTAGE OF TOTAL
				BigDecimal percentage = account.getConfirmedBalance(this.asset.getKey()).divide(total, 8, RoundingMode.DOWN);
				
				//CALCULATE AMOUNT
				BigDecimal accountAmount = amount.multiply(percentage);
				
				//ROUND AMOUNT
				if(assetToPay.isDivisible())
				{
					accountAmount = accountAmount.setScale(8, RoundingMode.DOWN);
				}
				else
				{
					accountAmount = accountAmount.setScale(0, RoundingMode.DOWN).setScale(8);
				}
				
				//CHECK IF AMOUNT NOT ZERO
				if(accountAmount.compareTo(BigDecimal.ZERO) > 0)
				{
					Payment payment = new Payment(account, assetToPay.getKey(), accountAmount);
					payments.add(payment);
				}
			}
			
			new MultiPaymentFrame(this.asset, payments);
		}
		catch(Exception e)
		{
			//CHECK WHERE PARSING ERROR HAPPENED
			switch(parsing)
			{
			case 1:
				
				JOptionPane.showMessageDialog(new JFrame(), "Invalid holders to pay!", "Error", JOptionPane.ERROR_MESSAGE);
				break;
				
			case 2:
				
				JOptionPane.showMessageDialog(new JFrame(), "Invalid amount to pay!", "Error", JOptionPane.ERROR_MESSAGE);
				break;
			}
		}
	}
}
