package Division.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import Division.Claimer;

public class PieChartDisplay extends JPanel{

	private static final long serialVersionUID = 1L;
	private BufferedImage buffer;
	private ReentrantLock lock;
	private List<Claimer> claimers;
	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 String title;
	double moneyTotal = 0;
	
	public PieChartDisplay(List<Claimer> claimers, String title){
		this.claimers = claimers;
		this.title = title;
        lock=new ReentrantLock();
		setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder()));
        addMouseListener(new Mouse(this));
        
        for(Claimer c : claimers){
        	moneyTotal += c.getReceived();
        }
	}
	
	@Override
	public Dimension getPreferredSize(){
		return new Dimension(claimers.size() * 80 + 60, claimers.size() * 80 + 100);
	}
	
	public void paintComponent(Graphics g){
		if (lock.isLocked())return;
        lock.lock();
        try{
            if (buffer==null||buffer.getWidth()!=getWidth()||buffer.getHeight()!=getHeight())buffer=new BufferedImage(getWidth(),getHeight(),BufferedImage.TYPE_INT_RGB);
            Graphics g2=buffer.getGraphics();
            paintComponent(g2);
            
            int h=getHeight()-100;
            int w=getWidth()-50;
            g2.setColor(Color.WHITE);
            g2.fillRect(0,0,getWidth(),getHeight());
            h-=10;
            
            FontMetrics fM=g.getFontMetrics();
            int fh=fM.getHeight();
            int fx=(int)(getWidth()-fM.getStringBounds(title,g).getWidth())/2;
            g2.setColor(Color.BLACK);
            g2.drawString(title,fx,40);
            w=Math.min(w,h);
            h=Math.min(w,h);
            int xp=(getWidth()-w)/2;
            int yp=(getHeight()-h)/2;
            if(claimers != null && claimers.size() > 0){
                int a=0;
                
                for(int x = 0; x < claimers.size() - 1; x++){
                	g2.setColor(colors[x]);
                	g2.fillArc(xp,yp,w,h,a,(int)((claimers.get(x).getReceived()/moneyTotal)*360));
                	g2.setColor(Color.BLACK);
                    g2.drawArc(xp,yp,w,h,a,(int)((claimers.get(x).getReceived()/moneyTotal)*360));

                    int lx=(int)(xp+(w/2)+(w/2.5)*Math.cos(2*Math.PI*(a+((claimers.get(x).getReceived()/moneyTotal)*180))/360.0));
                    int ly=(int)(yp+(h/2)-(h/2.2)*Math.sin(2*Math.PI*(a+((claimers.get(x).getReceived()/moneyTotal)*180))/360.0));
                    String l=(Math.round((claimers.get(x).getReceived()/moneyTotal)*1000)/10.0)+"%";
                    lx-=fM.getStringBounds(l,g).getWidth()/2;
                    ly+=fh/2;
                    g2.setColor(Color.WHITE);
                    g2.fillRect(lx-4,ly-fh-2,(int)fM.getStringBounds(l,g).getWidth()+8,fh+8);
                    g2.setColor(Color.BLACK);
                    g2.drawRect(lx-4,ly-fh-2,(int)fM.getStringBounds(l,g).getWidth()+8,fh+8);
                    g2.drawString(l,lx,ly);

                    a+=(int)((claimers.get(x).getReceived()/moneyTotal)*360);
                }


                g2.setColor(colors[claimers.size()-1]);
                g2.fillArc(xp,yp,w,h,a,360-a);
                g2.setColor(Color.BLACK);
                g2.drawArc(xp,yp,w,h,a,360-a);

                int lx=(int)(xp+(w/2)+(w/2.5)*Math.cos(2*Math.PI*(a+((claimers.get(claimers.size()-1).getReceived()/moneyTotal)*180))/360.0));
                int ly=(int)(yp+(h/2)-(h/2.2)*Math.sin(2*Math.PI*(a+((claimers.get(claimers.size()-1).getReceived()/moneyTotal)*180))/360.0));

                String l=(Math.round((claimers.get(claimers.size()-1).getReceived()/moneyTotal)*1000)/10.0)+"%";
                lx-=fM.getStringBounds(l,g).getWidth()/2;
                ly+=fh/2;
                g2.setColor(Color.WHITE);
                g2.fillRect(lx-4,ly-fh-2,(int)fM.getStringBounds(l,g).getWidth()+8,fh+8);
                g2.setColor(Color.BLACK);
                g2.drawRect(lx-4,ly-fh-2,(int)fM.getStringBounds(l,g).getWidth()+8,fh+8);
                g2.drawString(l,lx,ly);                

                int cw=getWidth()/(claimers.size()+1);
                int ty=getHeight()-15;
                for (int x=0;x<claimers.size();x++){
                	g2.setColor(Color.BLACK);
                    String t="Player "+(x+1);
                    int tx=25+(x+1)*cw-(int)((fM.getStringBounds(t,g).getWidth()+40)/2);
                    g2.drawString(t,tx,ty);
                    
                    g2.setColor(colors[x]);
                    tx-=30;
                    int by=ty-fh-((20-fh)/2);
                    g2.fillRect(tx,by,25,25);
                    g2.setColor(Color.BLACK);
                    g2.drawRect(tx,by,25,25);
                }
            }
            g.drawImage(buffer,0,0,null);
        }
        catch(Exception e){}
        lock.unlock();
	}
	
	class Mouse implements MouseListener {
        private JComponent frame;
        Mouse(JComponent 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 Graph");
                    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){}
    }
}
