package Matrix2P;

import Common.Matrix;

import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.*;
import java.util.ArrayList;

/**
 * Author: Max Buegler - max@sarstech.com
 * Date: Oct 17, 2009
 * Time: 7:45:55 PM
 */
public class FindProbabilityDevice implements GameAlgorithm{
    private double p1po,p2po;

    public FindProbabilityDevice() {
        p1po=0;
        p2po=0;
    }

    public String getDescriptor() {
        return "Find probability devices [payoff=("+p1po+","+p2po+") ]";
    }

        public void settings(ActionListener ul) {
        final ActionListener ul2=ul;
        final JFrame settingsFrame=new JFrame("Find probability devices 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("Finds probability devices yielding to the specified payoffs.");
                    aboutPanel.add(about);
                settingsFrame.add(aboutPanel,cons);

                JPanel settingsPanel=new JPanel();
                    settingsPanel.setLayout(new GridLayout(3,2));
                    settingsPanel.add(new JLabel("Payoff pl 1"));
                    final JTextField a1=new JTextField(p1po+"");
                    settingsPanel.add(a1);
                    settingsPanel.add(new JLabel("Payoff pl 2"));
                    final JTextField a2=new JTextField(p2po+"");
                    settingsPanel.add(a2);
                    JPanel button1=new JPanel();
                        button1.setLayout(new GridLayout(1,2));
                        JButton ok=new JButton("OK");
                        ok.addActionListener(new ActionListener(){
                            public void actionPerformed(ActionEvent e) {
                                try{
                                    p1po=Double.parseDouble(a1.getText());
                                }catch(Exception ex){
                                    JOptionPane.showMessageDialog(settingsFrame,"Please enter a real value for 'Payoff p1'");
                                    return;
                                }
                                try{
                                    p2po=Double.parseDouble(a2.getText());
                                }catch(Exception ex){
                                    JOptionPane.showMessageDialog(settingsFrame,"Please enter a real value for 'Payoff pl 2'");
                                    return;
                                }
                                ul2.actionPerformed(null);
                                settingsFrame.setVisible(false);
                            }
                        });
                        button1.add(new JLabel());
                        button1.add(ok);
                        settingsPanel.add(button1);
                    JPanel button2=new JPanel();
                        button2.setLayout(new GridLayout(1,2));
                        JButton cancel=new JButton("Cancel");
                        cancel.addActionListener(new ActionListener(){
                            public void actionPerformed(ActionEvent e) {
                                settingsFrame.setVisible(false);
                            }
                        });
                        button2.add(cancel);
                        button2.add(new JLabel());
                        settingsPanel.add(button2);
                cons=new GridBagConstraints();
                cons.weightx=0.5;
                cons.weighty=0.5;
                cons.gridx=0;
                cons.gridy=1;
                cons.gridheight=3;
                cons.gridwidth=1;
                cons.fill=GridBagConstraints.HORIZONTAL;
                settingsFrame.add(settingsPanel,cons);



                settingsFrame.setSize(400,400);
                settingsFrame.setVisible(true);

    }
    class Payoff{
        private double p1,p2;
        private int a1,a2;
        Payoff(double p1, double p2, int a1, int a2){this.p1 = p1;this.p2 = p2;this.a1=a1;this.a2=a2;}
        public double getP1(){return p1;}
        public double getP2(){return p2;}
        public double getA1(){return a1;}
        public double getA2(){return a2;}
        public boolean equals(Object e){
            if (!(e instanceof Payoff))return false;
            Payoff p=(Payoff)e;
            return p.p1==p1&&p.p2==p2;
        }

    }
    public void run(GameMatrix m, ActionListener finish) {
        ArrayList<Payoff> payoffs=new ArrayList<Payoff>();
        for (int x=0;x<m.getActionsP1();x++){
            for (int y=0;y<m.getActionsP2();y++){
                Payoff p=new Payoff(m.getP1()[x][y],m.getP2()[x][y],x,y);
                if (!payoffs.contains(p)){
                    payoffs.add(p);
                    if (p.getP1()==p1po&&p.getP2()==p2po){
                        System.out.println("P*=");
                        for (int q=0;q<m.getActionsP1();q++){
                            System.out.print("[   ");
                            for (int r=0;r<m.getActionsP2();r++){
                                if (x==q&&y==r)
                                    System.out.print("1.0");
                                else System.out.print("0.0");
                                if (r<m.getActionsP2()-1)System.out.print("    ");
                                else System.out.println("   ]");
                            }
                        }
                    }
                }
            }
        }
        for (int x=0;x<payoffs.size();x++){
            for (int y=x+1;y<payoffs.size();y++){
                if (payoffs.get(x).getP1()==payoffs.get(x).getP2()&&payoffs.get(y).getP1()==payoffs.get(y).getP2()&&p2po==p1po){
                    try{
                        Matrix mat=new Matrix(new double[][]{
                                {payoffs.get(x).getP1(),payoffs.get(y).getP1()},
                                {1,1}
                        });
                        Matrix sol=mat.solve(new Matrix(new double[][]{{p1po},{1}}));
                        if (sol.getValue(0,0)>0&&sol.getValue(1,0)>0){
                            System.out.println("P*=");
                            for (int q=0;q<m.getActionsP1();q++){
                                System.out.print("[   ");
                                for (int r=0;r<m.getActionsP2();r++){
                                    if (payoffs.get(x).getA2()==r&&payoffs.get(x).getA1()==q)
                                        System.out.print(sol.getValue(0,0));
                                    else if (payoffs.get(y).getA2()==r&&payoffs.get(y).getA1()==q)
                                        System.out.print(sol.getValue(1,0));
                                    else System.out.print("0.0");
                                    if (r<m.getActionsP2()-1)System.out.print("    ");
                                    else System.out.println("   ]");
                                }
                            }
                        }
                    }
                    catch(Exception ex){}

                }
                else{
                    try{
                        Matrix mat=new Matrix(new double[][]{
                                {payoffs.get(x).getP1(),payoffs.get(y).getP1(),0},
                                {payoffs.get(x).getP2(),payoffs.get(y).getP2(),0},
                                {1,1,0}
                        });
                        Matrix sol=mat.solve(new Matrix(new double[][]{{p1po},{p2po},{1}}));
                        if (sol.getValue(0,0)>0&&sol.getValue(1,0)>0){
                            System.out.println("P*=");
                            for (int q=0;q<m.getActionsP1();q++){
                                System.out.print("[   ");
                                for (int r=0;r<m.getActionsP2();r++){
                                    if (payoffs.get(x).getA2()==r&&payoffs.get(x).getA1()==q)
                                        System.out.print(sol.getValue(0,0));
                                    else if (payoffs.get(y).getA2()==r&&payoffs.get(y).getA1()==q)
                                        System.out.print(sol.getValue(1,0));
                                    else System.out.print("0.0");
                                    if (r<m.getActionsP2()-1)System.out.print("    ");
                                    else System.out.println("   ]");
                                }
                            }
                        }
                    }
                    catch(Exception ex){}
                }
            }
        }

        for (int x=0;x<payoffs.size();x++){
            for (int y=x+1;y<payoffs.size();y++){
                for (int z=y+1;z<payoffs.size();z++){
                    Matrix mat=new Matrix(new double[][]{
                            {payoffs.get(x).getP1(),payoffs.get(y).getP1(),payoffs.get(z).getP1()},
                            {payoffs.get(x).getP2(),payoffs.get(y).getP2(),payoffs.get(z).getP2()},
                            {1,1,1}
                    });
                    try{
                        Matrix sol=mat.solve(new Matrix(new double[][]{{p1po},{p2po},{1}}));
                        if (sol.getValue(0,0)>0&&sol.getValue(1,0)>0&&sol.getValue(2,0)>0){
                            System.out.println("P*=");
                            for (int q=0;q<m.getActionsP1();q++){
                                System.out.print("[   ");
                                for (int r=0;r<m.getActionsP2();r++){
                                    if (payoffs.get(x).getA2()==r&&payoffs.get(x).getA1()==q)
                                        System.out.print(sol.getValue(0,0));
                                    else if (payoffs.get(y).getA2()==r&&payoffs.get(y).getA1()==q)
                                        System.out.print(sol.getValue(1,0));
                                    else if (payoffs.get(z).getA2()==r&&payoffs.get(z).getA1()==q)
                                        System.out.print(sol.getValue(2,0));
                                    else System.out.print("0.0");
                                    if (r<m.getActionsP2()-1)System.out.print("    ");
                                    else System.out.println("   ]");
                                }
                            }
                        }
                    }
                    catch(Exception ex){}
                }
            }
        }
        finish.actionPerformed(null);
    }

    public void stop() {

    }
}
