import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;

public class rotation extends Applet implements Runnable{

    Thread th = null;
    double r3 = 1.732051;
    double pi = 3.141592;
    double st;
    int mtd[][] = {{0,1,1,1,0},{1,1,1,2,0},{2,2,2,2,2},{2,3,3,3,0},{0,3,3,3,0}};
    int si = 60,cr = 20;
    Color co[] = new Color[3];
    int sx = 2,sy = 2,dx,dy;
    int sd = 0;
    int rd,fg = 0,dr = 1;
    Image os;
    Graphics og;
    Button tr;

    public void init(){
       
        setBackground(Color.white);
        os = createImage(320,300);
        og = os.getGraphics();
        st = 0;
        co[0] = new Color(240,10,10);
        co[1] = new Color(10,10,240);
        co[2] = new Color(10,240,10);
        setLayout(new BorderLayout());
        Panel pan = new Panel();
        pan.setLayout(new FlowLayout());
        pan.add(tr = new Button("   << reverse >>   "));
        add("South",pan);
        tr.addActionListener(new ActionListener(){
           public void actionPerformed(ActionEvent e){
               dr = -1 * dr;
           }
        });
        addMouseListener(
            new MouseAdapter(){
                public void mousePressed(MouseEvent e){
                    if(fg == 0){
                        dy = (int)((e.getY() - 20) / (si * r3 / 2));
                        dx = (int)((e.getX() - (dy % 2 + 1) * 20) / si);
                        sx = dx ; sy = dy ;
                        if(sy == 2){
                            sd = -1;
                        }else{
                            sd = 0;
                        }
                        if((((sx == 1) || (sx == 2)) && ((sy > 0) && (sy < 4))) || ((sx == 3) && (sy == 2))){
                            fg = 1;
                            th.resume();
                        }
                    }
                }
            }
        );
    }

    public void paint(Graphics g){

        og.setColor(Color.white); 
        og.fillRect(0,0,320,300);
        og.setColor(Color.black);

        for(int ix = 0;ix < 5;ix ++){
            for(int iy = 0;iy < 5;iy ++){
                if(mtd[iy][ix] != 0){
                    if(sy == 2){
                        sd = -1;
                    }else{
                        sd = 0;
                    }
                    og.setColor(co[mtd[iy][ix] - 1]);
                    if((ix == sx + 1 + sd) && (iy == sy - 1)){
                        og.fillOval((int)(Math.round((si * sx + ((sy % 2) * (si / 2)) + 40 - cr) + (si * Math.cos(st + (pi / 3))))) , (int)(Math.round(((si * r3 / 2) * sy + 40 - cr) - (si * Math.sin(st + (pi / 3))))),cr * 2,cr * 2);
                    }else if((ix == sx + sd) && (iy == sy - 1)){
                        og.fillOval((int)(Math.round((si * sx + ((sy % 2) * (si / 2)) + 40 - cr) + (si * Math.cos(st + (2 * pi / 3))))) , (int)(Math.round(((si * r3 / 2) * sy + 40 - cr) - (si * Math.sin(st + (2 * pi / 3))))),cr * 2,cr * 2);
                    }else if((ix == sx - 1) && (iy == sy)){
                        og.fillOval((int)(Math.round((si * sx + ((sy % 2) * (si / 2)) + 40 - cr) + (si * Math.cos(st + (3 * pi / 3))))) , (int)(Math.round(((si * r3 / 2) * sy + 40 - cr) - (si * Math.sin(st + (3 * pi / 3))))),cr * 2,cr * 2);
                    }else if((ix == sx + sd) && (iy == sy + 1)){
                        og.fillOval((int)(Math.round((si * sx + ((sy % 2) * (si / 2)) + 40 - cr) + (si * Math.cos(st + (4 * pi / 3))))) , (int)(Math.round(((si * r3 / 2) * sy + 40 - cr) - (si * Math.sin(st + (4 * pi / 3))))),cr * 2,cr * 2);
                    }else if((ix == sx + 1 + sd) && (iy == sy + 1)){
                        og.fillOval((int)(Math.round((si * sx + ((sy % 2) * (si / 2)) + 40 - cr) + (si * Math.cos(st + (5 * pi / 3))))) , (int)(Math.round(((si * r3 / 2) * sy + 40 - cr) - (si * Math.sin(st + (5 * pi / 3))))),cr * 2,cr * 2);
                    }else if((ix == sx + 1) && (iy == sy)){
                        og.fillOval((int)((Math.round(si * sx + ((sy % 2) * (si / 2)) + 40 - cr) + (si * Math.cos(st + (6 * pi / 3))))) , (int)(Math.round(((si * r3 / 2) * sy + 40 - cr) - (si * Math.sin(st + (6 * pi / 3))))),cr * 2,cr * 2);
                    }else{
                        og.fillOval((int)(Math.round((si * ix + ((iy % 2) * (si / 2)) + 40 - cr))) , (int)(Math.round(((si * r3 / 2) * iy + 40 - cr))),cr * 2,cr * 2);
                    }
                }
            }
        }
        g.drawImage(os,0,0,this );
    }

    public void start(){    
        if(th == null){
            th = new Thread(this);
            th.start();
        }
        th.suspend();
    }

    public void stop(){
        th = null;
    }

    public void run(){
        while(th != null){
            try{
                if(dr == 1){
                    st = st + (pi / 50);
                    if(st > (pi / 3)){
                        rd = mtd[sy][sx + 1];
                        mtd[sy][sx + 1] = mtd[sy + 1][sx + 1 + sd];
                        mtd[sy + 1][sx + 1 + sd] = mtd[sy + 1][sx + sd];
                        mtd[sy + 1][sx + sd] = mtd[sy][sx - 1];
                        mtd[sy][sx - 1] = mtd[sy - 1][sx + sd];
                        mtd[sy - 1][sx + sd] = mtd[sy - 1][sx + 1 + sd];
                        mtd[sy - 1][sx + 1 + sd] = rd;
                        st = 0;
                        fg = 0;
                        th.suspend();
                    }
                }else{
                    st = st - (pi / 50);
                    if(st < -1 * (pi / 3)){
                        rd = mtd[sy][sx + 1];
                        mtd[sy][sx + 1] = mtd[sy - 1][sx + 1 + sd];
                        mtd[sy - 1][sx + 1 + sd] = mtd[sy - 1][sx + sd];
                        mtd[sy - 1][sx + sd] = mtd[sy][sx - 1];
                        mtd[sy][sx - 1] = mtd[sy + 1][sx + sd];
                        mtd[sy + 1][sx + sd] = mtd[sy + 1][sx + 1 + sd];
                        mtd[sy + 1][sx + 1 + sd] = rd;
                        st = 0;
                        fg = 0;
                        th.suspend();
                    }
                }
                Thread.sleep(20);
            }
            catch (InterruptedException e){ }
            repaint();
        }
    }
    public void update(Graphics g)
    {
        paint(g) ;
    }
}