package Common;


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

/**
 * Author: Max Buegler - max@sarstech.com
 * Date: Oct 15, 2009
 * Time: 7:21:01 PM
 */
public class PieChartFrame  extends JFrame {
    private final Color[] colors=new Color[]{Color.RED,Color.GREEN,Color.BLUE, Color.PINK,Color.ORANGE,Color.BLACK,Color.MAGENTA,Color.CYAN,Color.YELLOW,Color.DARK_GRAY};
    private double[] data;
    private BufferedImage buffer;
    private String title;
    private ReentrantLock lock;
    public PieChartFrame(String title, double[] data){
        super(title+" (Right click to save)");
        this.lock=new ReentrantLock();
        super.setSize(350,350);
        super.setVisible(true);
        this.title=title;
        this.data=data;
        double sum=0;
        for (int x=0;x<data.length;x++)sum+=data[x];
        for (int x=0;x<data.length;x++)data[x]/=sum;
        super.addMouseListener(new Mouse(this));

    }

    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){}
    }

    public void paint(Graphics g2){
        if (lock==null||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;
            w=Math.min(w,h);
            h=Math.min(w,h);
            int xp=(getWidth()-w)/2;
            int yp=(getHeight()-h)/2;
            FontMetrics fM=g.getFontMetrics();
            int fh=fM.getHeight();
            int fx=(int)(getWidth()-fM.getStringBounds(title,g).getWidth())/2;
            g.setColor(Color.BLACK);
            g.drawString(title,fx,40);

            if (data!=null&&data.length>0){
                int a=0;
                for (int x=0;x<data.length-1;x++){
                    g.setColor(colors[x]);
                    g.fillArc(xp,yp,w,h,a,(int)(data[x]*360));
                    g.setColor(Color.BLACK);
                    g.drawArc(xp,yp,w,h,a,(int)(data[x]*360));

                    int lx=(int)(xp+(w/2)+(w/2.5)*Math.cos(2*Math.PI*(a+(data[x]*180))/360.0));
                    int ly=(int)(yp+(h/2)-(h/2.2)*Math.sin(2*Math.PI*(a+(data[x]*180))/360.0));

                    String l=(Math.round(data[x]*1000)/10.0)+"%";
                    lx-=fM.getStringBounds(l,g).getWidth()/2;
                    ly+=fh/2;
                    g.setColor(Color.WHITE);
                    g.fillRect(lx-4,ly-fh-2,(int)fM.getStringBounds(l,g).getWidth()+8,fh+8);
                    g.setColor(Color.BLACK);
                    g.drawRect(lx-4,ly-fh-2,(int)fM.getStringBounds(l,g).getWidth()+8,fh+8);
                    g.drawString(l,lx,ly);
                    a+=(int)(data[x]*360);
                }
                g.setColor(colors[data.length-1]);
                g.fillArc(xp,yp,w,h,a,360-a);
                g.setColor(Color.BLACK);
                g.drawArc(xp,yp,w,h,a,360-a);
                int lx=(int)(xp+(w/2)+(w/2.5)*Math.cos(2*Math.PI*(a+(data[data.length-1]*180))/360.0));
                int ly=(int)(yp+(h/2)-(h/2.2)*Math.sin(2*Math.PI*(a+(data[data.length-1]*180))/360.0));

                String l=(Math.round(data[data.length-1]*1000)/10.0)+"%";
                lx-=fM.getStringBounds(l,g).getWidth()/2;
                ly+=fh/2;
                g.setColor(Color.WHITE);
                g.fillRect(lx-4,ly-fh-2,(int)fM.getStringBounds(l,g).getWidth()+8,fh+8);
                g.setColor(Color.BLACK);
                g.drawRect(lx-4,ly-fh-2,(int)fM.getStringBounds(l,g).getWidth()+8,fh+8);
                g.drawString(l,lx,ly);

                int cw=getWidth()/(data.length+1);
                int ty=getHeight()-15;
                for (int x=0;x<data.length;x++){
                    g.setColor(Color.BLACK);
                    String t="Player "+(x+1);
                    int tx=25+(x+1)*cw-(int)((fM.getStringBounds(t,g).getWidth()+40)/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);
        }
        catch(Exception ex){}
        lock.unlock();
    }
    class Data{
        private double[] data;
        public Data(double[] data) {
            this.data = data;
        }

        public double[] getData() {
            return data;
        }
    }
}
