//[Update:[Tue Nov 05 IST 2019]]
/*History:
**Thu Oct 24 2019
   Started.
**Wed Oct 30 2019
 First working version.
**Mon Nov 04 2019
 Load and save.
*/

/*
(%i1)  A:matrix([ct, st,0],[-st,ct,0],[0,0,1]);
                                [  ct   st  0 ]
                                [             ]
(%o8)                           [ - st  ct  0 ]
                                [             ]
                                [  0    0   1 ]

(%i2) B:matrix([cs,0,ss],[0,1,0],[-ss,0,cs]);
                                [  cs   0  ss ]
                                [             ]
(%o2)                           [  0    1  0  ]
                                [             ]
                                [ - ss  0  cs ]
(%i3) C:matrix([1,0,0],[0,cr,sr],[0,-sr,cr]);
                                [ 1   0    0  ]
                                [             ]
(%o3)                           [ 0   cr   sr ]
                                [             ]
                                [ 0  - sr  cr ]
(%i4) A.B.C;
                [  cs ct   cr st - ct sr ss  sr st + cr ct ss ]
                [                                             ]
(%o9)           [ - cs st  sr ss st + cr ct  ct sr - cr ss st ]
                [                                             ]
                [  - ss        - cs sr            cr cs       ]
 */
import java.util.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
import javax.swing.*;

public class Pose extends JPanel
    implements ActionListener {
    double[][] mat;
    JFrame gui;
    JTextField rfld, sfld, tfld, xfld, yfld, zfld, xsfld, ysfld, zsfld;
    JButton updt;
    double r,s,t, xScale, yScale, zScale;
    Screen scr;
    Vec3 origin;
    
    public Pose(Screen scr, double r, double s, double t, double x, double y, double z) {
        this.scr = scr;
        this.r = r;
        this.s = s;
        this.t = t;
        makeMat();
        origin = new Vec3(x,y,z);
        xScale = yScale = zScale = 1.0;
        setLayout(new GridLayout(5,3));
        add(new JLabel("Angle")); add(new JLabel("Origin")); add(new JLabel("Scale"));
        rfld = tf();        xfld = tf(); xsfld = tf();
        sfld = tf();        yfld = tf(); ysfld = tf();
        tfld = tf();        zfld = tf(); zsfld = tf();



        updt = new JButton("Update");
        updt.addActionListener(this);
        add(updt);
        gui = new JFrame();
        gui.add(this);
        gui.pack();
        gui.setSize(200,400);
    }

    protected void save(PrintWriter pw) {
        pw.format("%f %f %f %f %f %f %f %f %f ",r,s,t,origin.x,origin.y,origin.z,xScale,yScale,zScale);
    }
    
    protected void load(Scanner scnr) {
        double tmpr,tmps,tmpt,tmpx,tmpy,tmpz,tmpxScale,tmpyScale,tmpzScale;
        System.err.println("Loading a pose");
        try {
            tmpr = scnr.nextDouble();
            tmps = scnr.nextDouble();
            tmpt = scnr.nextDouble();
            tmpx = scnr.nextDouble();
            tmpy = scnr.nextDouble();
            tmpz = scnr.nextDouble();
            tmpxScale = scnr.nextDouble();
            tmpyScale = scnr.nextDouble();
            tmpzScale = scnr.nextDouble();
        }
        catch(Exception ex) {
            System.err.println("Failed to load pose");
            ex.printStackTrace(System.err);
            return;
        }
        r = tmpr; s = tmps; t = tmpt;
        origin = new Vec3(tmpx, tmpy, tmpz);
        xScale = tmpxScale; yScale = tmpyScale; zScale = tmpzScale;
        makeMat();
        showGui();
    }
    private JTextField tf() {
        JTextField tmp = new JTextField();
        add(tmp);
        return tmp;
    }

    Vec3 getScales() {
        return new Vec3(xScale, yScale, zScale);
    }
    
    private double prod(int i, int j) {
        return mat[i][0]*mat[j][0]+mat[i][1]*mat[j][1]+mat[i][2]*mat[j][2];
    }

    private static final double d2r = Math.PI/180.0;
    private void makeMat() {
        mat = new double[3][3];
        double r1 = -r*d2r;
        double s1 = s*d2r;
        double t1 = -t*d2r;
        double cr = Math.cos(r1); double sr = Math.sin(r1);
        double cs = Math.cos(s1); double ss = Math.sin(s1);
        double ct = Math.cos(t1); double st = Math.sin(t1);
        mat[0][0] = cs*ct;  mat[0][1] = cr*st-ct*sr*ss; mat[0][2] = sr*st+cr*ct*ss;
        mat[1][0] = -cs*st; mat[1][1] = sr*ss*st+cr*ct; mat[1][2] = ct*sr-cr*ss*st;
        mat[2][0] = -ss;    mat[2][1] = -cs*sr;         mat[2][2] = cr*cs;

        for(int i=0;i<3;i++) {
            for(int j=0;j<3;j++)
                System.err.print(mat[i][j]+" ");
            System.err.println();
        }
        System.err.println("--------------");
        for(int i=0;i<3;i++) {
            for(int j=0;j<3;j++)
                System.err.print(prod(i,j)+" ");
            System.err.println();
        }
        System.err.println("--------------");
    }

    public Vec3 getOrigin() {
        return origin;
    }
    public void actionPerformed(ActionEvent ae) {
        try {
            r = Double.parseDouble(rfld.getText());
            s = Double.parseDouble(sfld.getText());
            t = Double.parseDouble(tfld.getText());
            origin.x = Double.parseDouble(xfld.getText());
            origin.y = Double.parseDouble(yfld.getText());
            origin.z = Double.parseDouble(zfld.getText());
            xScale = Double.parseDouble(xsfld.getText());
            yScale = Double.parseDouble(ysfld.getText());
            zScale = Double.parseDouble(zsfld.getText());
        }
        catch(Exception ex) {
            ex.printStackTrace(System.err);
        }
        makeMat();
        scr.repaint();
    }
    public void showGui() {
        rfld.setText(""+r); sfld.setText(""+s); tfld.setText(""+t);
        xfld.setText(""+origin.x); yfld.setText(""+origin.y);        zfld.setText(""+origin.z);
        xsfld.setText(""+xScale); ysfld.setText(""+yScale); zsfld.setText(""+zScale); 
    }
    public double[][] getMat() {
        return mat;
    }

    public Vec3 xTimes(double mult) {
        return new Vec3(mat[0][0]*mult,mat[1][0]*mult,mat[2][0]*mult);
    }
    
    public Vec3 yTimes(double mult) {
        return new Vec3(mat[0][1]*mult,mat[1][1]*mult,mat[2][1]*mult);
    }
    
    public Vec3 zTimes(double mult) {
        return new Vec3(mat[0][2]*mult,mat[1][2]*mult,mat[2][2]*mult);
    }

    public Vec3 wrt(Vec3 old) {
        return origin.plus(xTimes(xScale*old.x)).plus(yTimes(yScale*old.y)).plus(zTimes(zScale*old.z));
    }
    
    public Vec3 rot(Vec3 v) {
        return new Vec3(
                        mat[0][0]*v.x+mat[0][1]*v.y+mat[0][2]*v.z,
                        mat[1][0]*v.x+mat[1][1]*v.y+mat[1][2]*v.z,
                        mat[2][0]*v.x+mat[2][1]*v.y+mat[2][2]*v.z
                        );                        
    }
    
    public Vec3 invRot(Vec3 v) {
        return new Vec3(
                        mat[0][0]*v.x+mat[1][0]*v.y+mat[2][0]*v.z,
                        mat[0][1]*v.x+mat[1][1]*v.y+mat[2][1]*v.z,
                        mat[0][2]*v.x+mat[1][2]*v.y+mat[2][2]*v.z
                        );                       
    }
    

}
