package Matrix2P;

import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.concurrent.locks.ReentrantLock;
import java.io.File;

/**
 * Author: Max Buegler - max@sarstech.com
 * Date: Oct 16, 2009
 * Time: 11:46:58 PM
 */
public class BestReplyDiagram extends JFrame implements GameAlgorithm{
    private int q0,q1,p0,p1;
    private double p,q;
    private final Color[] colors=new Color[]{Color.RED,Color.GREEN};
    private BufferedImage buffer;
    private ReentrantLock lock;


    public BestReplyDiagram(){
        super("Wega Best Reply Diagram (Right click to save)");
        super.addMouseListener(new Mouse(this));
        this.lock=new ReentrantLock();

    }

    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("Draws the best reply diagrams and indicates the resulting equiliria");
            aboutPanel.add(about);
        settingsFrame.add(aboutPanel,cons);

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


    public void run(GameMatrix m, ActionListener finish) {
        if (m.getActionsP1()!=2||m.getActionsP2()!=2){
            JOptionPane.showMessageDialog(this,"Only applicable for 2x2 game matrixes");
            finish.actionPerformed(null);
            return;
        }
        p=-1;
        q=-1;
        double[][] pl1=m.getP1();
        double[][] pl2=m.getP2();
        double den=pl2[0][0]-pl2[1][0]-pl2[0][1]+pl2[1][1];
        if (den!=0)p=(pl2[0][0]-pl2[0][1])/den;
        if (p>1)p=-1;

        den=pl1[0][0]-pl1[1][0]-pl1[0][1]+pl1[1][1];
        if (den!=0)q=(pl1[0][0]-pl1[1][0])/den;
        if (q>1)q=-1;
        q0=m.getP1BestReply(0);
        q1=m.getP1BestReply(1);
        p0=m.getP2BestReply(0);
        p1=m.getP2BestReply(1);
        System.out.println("Best reply to pl2 action 1: "+(q0+1));
        System.out.println("Best reply to pl2 action 2: "+(q1+1));
        System.out.println("Best reply to pl1 action 1: "+(p0+1));
        System.out.println("Best reply to pl1 action 2: "+(p1+1));
        if (p1!=p0){
            System.out.print("Break even point p: ");
            if (p<0)System.out.println("None");
            else System.out.println(p);
        }
        if (q1!=q0){
            System.out.print("Break even point q: ");
            if (q<0)System.out.println("None");
            else System.out.println(q);
        }
        super.setSize(300,350);
        super.setVisible(true);
        super.repaint();
        finish.actionPerformed(null);
    }

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

    public String getDescriptor() {
        return "Best reply diagram";  //To change body of implemented methods use File | Settings | File Templates.
    }
    public void paint(Graphics g2){
        if (lock.isLocked())return;
        lock.lock();
        try{
            if (buffer==null||buffer.getWidth()!=getWidth()||buffer.getHeight()!=getHeight()){
                buffer=new BufferedImage(getWidth(),getHeight(),BufferedImage.TYPE_BYTE_INDEXED);
            }
            Graphics g=buffer.getGraphics();
            int h=getHeight()-100;
            int w=getWidth()-50;
            g.setColor(Color.WHITE);
            g.fillRect(0,0,getWidth(),getHeight());
            h-=10;
            FontMetrics fM=g.getFontMetrics();
            int fh=fM.getHeight();
            int fx=(int)(getWidth()-fM.getStringBounds("Best reply diagram",g).getWidth())/2;
            g.setColor(Color.BLACK);
            g.drawString("Best reply diagram",fx,40);

            g.drawRect(25,50,w,h);
            fx=(int)(25-fM.getStringBounds("q",g).getWidth())/2;
            if (fx<0)fx=0;
            int fy=50+(h+fh)/2;
            if (q>0.4&&q<0.6)fy+=20;
            g.drawString("q",fx,fy);
            fx=(int)(w-fM.getStringBounds("p",g).getWidth())/2;
            if (p>0.4&&p<0.6)fx-=30;
            g.drawString("p",25+fx,50+h+fh);
            fx=(int)(25-fM.getStringBounds("0",g).getWidth())/2;
            g.drawString("0",fx,50+h+fh);
            fx=(int)(25-fM.getStringBounds("1",g).getWidth())/2;
            g.drawString("1",fx,50+fh);
            g.drawString("1",25+w,50+h+fh);

            String ps=p+"";
            if (ps.length()>4)ps=ps.substring(0,4);
            String qs=q+"";
            if (qs.length()>4)qs=qs.substring(0,4);
            fx=(int)(25-fM.getStringBounds(qs,g).getWidth())/2;
            if (fx<5)fx=5;
            if (q>0&&q<1&&q1!=q0)
                g.drawString(qs,fx,50+(int)((1-q)*h)+fh);
            if (p>0&&p<1&&p0!=p1)
                g.drawString(ps,25+(int)(p*w),50+h+fh);
            Graphics2D g3 = (Graphics2D)g;
            g3.setStroke(new BasicStroke(3));
            g3.setColor(colors[0]);
            if (q0==q1||q<0){
                if (q0==0)g3.drawLine(25,50,25,50+h);
                else g3.drawLine(25+w,50,25+w,50+h);
            }
            else{
                if (q0==0){
                    g3.drawLine(25,50+h,25,50+(int)((1-q)*h));
                    g3.drawLine(25+w,50+(int)((1-q)*h),25+w,50);
                }
                else{
                    g3.drawLine(25+w,50+h,25+w,50+(int)((1-q)*h));
                    g3.drawLine(25,50+(int)((1-q)*h),25,50);
                }
                g3.drawLine(25,50+(int)((1-q)*h),25+w,50+(int)((1-q)*h));
            }
            g3.setStroke(new BasicStroke(2));
            g3.setColor(colors[1]);
            if (p0==p1||p<0){
                if (p0==0)g3.drawLine(25,50+h,25+w,50+h);
                else g3.drawLine(25,50,25+w,50);
            }
            else{
                if (p0==0){
                    g3.drawLine(25,50+h,25+(int)(p*w),50+h);
                    g3.drawLine(25+(int)(p*w),50,25+w,50);
                }
                else {
                    g3.drawLine(25,50,25+(int)(p*w),50);
                    g3.drawLine(25+(int)(p*w),50+h,25+w,50+h);
                }
                g3.drawLine(25+(int)(p*w),50,25+(int)(p*w),50+h);
            }
            g3.setStroke(new BasicStroke(1));
            g3.setColor(Color.BLUE);
            if (q0!=q1&&p0!=p1){
                g3.drawLine(25+(int)(p*w)-4,50+(int)((1-q)*h)-4,25+(int)(p*w)+4,50+(int)((1-q)*h)+4);
                g3.drawLine(25+(int)(p*w)-4,50+(int)((1-q)*h)+4,25+(int)(p*w)+4,50+(int)((1-q)*h)-4);
            }
            if (q0==0&&p0==0){
                g3.drawLine(25-4,50+h-4,25+4,50+h+4);
                g3.drawLine(25-4,50+h+4,25+4,50+h-4);
            }
            if (q1==0&&p0==1){
                g3.drawLine(25-4,50-4,25+4,50+4);
                g3.drawLine(25-4,50+4,25+4,50-4);
            }
            if (q0==1&&p1==0){
                g3.drawLine(25+w-4,50+h-4,25+w+4,50+h+4);
                g3.drawLine(25+w-4,50+h+4,25+w+4,50+h-4);
            }
            if (q1==1&&p1==1){
                g3.drawLine(25+w-4,50-4,25+w+4,50+4);
                g3.drawLine(25+w-4,50+4,25+w+4,50-4);
            }
            if (p==1&&q0!=q1){
                g3.drawLine(25+w-4,50+h-4,25+w-4,50+(int)((1-q)*h)+4);
                g3.drawLine(25+w+4,50+h-4,25+w+4,50+(int)((1-q)*h)+4);
            }
            if (p==0&&p0!=p1){
                if (q0!=q1&&q!=1){
                    g3.drawLine(25+4,50+h-4,25+4,50+(int)((1-q)*h)+4);
                    g3.drawLine(25+4,50+h-4,25+4,50+(int)((1-q)*h)+4);
                }
                else if (q0==0){
                    g3.drawLine(25-4,50-4,25+4,50+4);
                    g3.drawLine(25-4,50+4,25+4,50-4);
                    g3.drawLine(25-4,50+h-4,25-4,50+4);
                    g3.drawLine(25+4,50+h-4,25+4,50+4);
                }
            }
            if (q==1&&p0!=p1){
                g3.drawLine(25+w-4,50-4,25+(int)(p*w)+4,50-4);
                g3.drawLine(25+w-4,50+4,25+(int)(p*w)+4,50+4);
                g3.drawLine(25+w-4,50-4,25+w+4,50+4);
                g3.drawLine(25+w-4,50+4,25+w+4,50-4);
            }
            if (q==0&&q0!=q1){
                if (p0!=p1&&p!=1){
                    g3.drawLine(25+4,50+h-4,25+(int)(p*w)-4,50+h-4);
                    g3.drawLine(25+4,50+h+4,25+(int)(p*w)-4,50+h+4);
                }
                else if (p0==0){
                    g3.drawLine(25+4,50+h-4,25+w-4,50+h-4);
                    g3.drawLine(25+4,50+h+4,25+w-4,50+h+4);

                    //g3.drawLine(25+w-4,50+h-4,25+w+4,50+h+4);
                    //g3.drawLine(25+w-4,50+h+4,25+w+4,50+h-4);
                }
            }

            
            g3.setStroke(new BasicStroke(1));
            int cw=w/3;
            int ty=getHeight()-15;
            for (int x=0;x<2;x++){
                g.setColor(Color.BLACK);
                String t="Player "+(x+1);
                int tx=55+(x+1)*cw-(int)((fM.getStringBounds(t,g).getWidth())/2);
                g.drawString(t,tx,ty);

                g.setColor(colors[x]);
                tx-=30;
                int by=ty-fh-((20-fh)/2);
                g.fillRect(tx,by,25,25);
                g.setColor(Color.BLACK);
                g.drawRect(tx,by,25,25);
            }
            g2.drawImage(buffer,0,0,null);
            setVisible(true);
        }
        catch(Exception ex){}
        lock.unlock();
    }

    class Mouse implements MouseListener {
        private JFrame frame;
        Mouse(JFrame frame) {
            this.frame = frame;
        }
        public void mouseClicked(MouseEvent e) {
            if (e.getButton()==MouseEvent.BUTTON3){
                lock.lock();
                try{
                    final JFileChooser fc = new JFileChooser();
                    fc.setName("Save Chart");
                    int retVal = fc.showSaveDialog(frame);
                    if (retVal==JFileChooser.APPROVE_OPTION){
                        File f=fc.getSelectedFile();
                        if (f.exists()){
                            retVal=JOptionPane.showConfirmDialog(frame,"Overwrite "+f.getName()+"?");
                            if (retVal!=JOptionPane.OK_OPTION)return;
                        }
                        int i=f.getName().lastIndexOf('.');
                        if (i>0){
                            String format=f.getName().substring(i+1);
                            ImageIO.write(buffer,format,f);
                        }
                        else{
                            ImageIO.write(buffer,"bmp",f);
                        }
                    }
                }
                catch(Exception ex){
                    JOptionPane.showMessageDialog(frame,"Could not save Image.");
                }
                lock.unlock();
                repaint();
            }
        }
        public void mousePressed(MouseEvent e){}
        public void mouseReleased(MouseEvent e){}
        public void mouseEntered(MouseEvent e){}
        public void mouseExited(MouseEvent e){}
    }

}
