package fr.alnotz.quaternion;

/**
 * Classe du quaternion dual, combinaison entre dual et quaternion.
 */
public class DualQuaternion implements IsDualQuaternion {
    private double rs;
    private double ri;
    private double rj;
    private double rk;
    private double ds;
    private double di;
    private double dj;
    private double dk;
    public DualQuaternion(){
        this.rs = 0;
        this.ri = 0;
        this.rj = 0;
        this.rk = 0;
        this.ds = 0;
        this.di = 0;
        this.dj = 0;
        this.dk = 0;
    }
    public DualQuaternion(Quaternion quaternion0, Quaternion quaternion1){
        this.rs = quaternion0.getS();
        this.ri = quaternion0.getI();
        this.rj = quaternion0.getJ();
        this.rk = quaternion0.getK();
        this.ds = quaternion1.getS();
        this.di = quaternion1.getI();
        this.dj = quaternion1.getJ();
        this.dk = quaternion1.getK();
    }
    public DualQuaternion(IsDual dual0, IsDual dual1, IsDual dual2, IsDual dual3){
        this.rs = dual0.getR();
        this.ri = dual1.getR();
        this.rj = dual2.getR();
        this.rk = dual3.getR();
        this.ds = dual0.getD();
        this.di = dual1.getD();
        this.dj = dual2.getD();
        this.dk = dual3.getD();
    }
    public DualQuaternion(double rs, double ri, double rj, double rk, double ds, double di, double dj, double dk){
        this.rs = rs;
        this.ri = ri;
        this.rj = rj;
        this.rk = rk;
        this.ds = ds;
        this.di = di;
        this.dj = dj;
        this.dk = dk;
    }
    @Override
    public IsQuaternion getR() {
        return new Quaternion(this.rs, this.ri, this.rj, this.rk);
    }

    @Override
    public IsQuaternion getD() {
        return new Quaternion(this.ds, this.di, this.dj, this.dk);
    }

    @Override
    public IsDual getS() {
        return new Dual(this.rs, this.ds);
    }

    @Override
    public IsDual getI() {
        return new Dual(this.ri, this.di);
    }

    @Override
    public IsDual getJ() {
        return new Dual(this.rj, this.dj);
    }

    @Override
    public IsDual getK() {
        return new Dual(this.rk, this.dk);
    }

    @Override
    public void setR(IsQuaternion quaternion) {
        this.rs = quaternion.getS();
        this.ri = quaternion.getI();
        this.rj = quaternion.getJ();
        this.rk = quaternion.getK();
    }

    @Override
    public void setD(IsQuaternion quaternion) {
        this.ds = quaternion.getS();
        this.di = quaternion.getI();
        this.dj = quaternion.getJ();
        this.dk = quaternion.getK();
    }

    @Override
    public void setS(IsDual dual) {
        this.rs = dual.getR();
        this.ds = dual.getD();

    }

    @Override
    public void setI(IsDual dual) {
        this.ri = dual.getR();
        this.di = dual.getD();
    }

    @Override
    public void setJ(IsDual dual) {
        this.rj = dual.getR();
        this.dj = dual.getD();
    }

    @Override
    public void setK(IsDual dual) {
        this.rk = dual.getR();
        this.dk = dual.getD();
    }
    @Override
    public double getRS() {
        return rs;
    }

    @Override
    public void setRS(double rs) {
        this.rs = rs;
    }

    @Override
    public double getRI() {
        return ri;
    }

    @Override
    public void setRI(double ri) {
        this.ri = ri;
    }

    @Override
    public double getRJ() {
        return rj;
    }

    @Override
    public void setRJ(double rj) {
        this.rj = rj;
    }

    @Override
    public double getRK() {
        return rk;
    }

    @Override
    public void setRK(double rk) {
        this.rk = rk;
    }

    @Override
    public double getDS() {
        return ds;
    }

    @Override
    public void setDS(double ds) {
        this.ds = ds;
    }

    @Override
    public double getDI() {
        return di;
    }

    @Override
    public void setDI(double di) {
        this.di = di;
    }

    @Override
    public double getDJ() {
        return dj;
    }

    @Override
    public void setDJ(double dj) {
        this.dj = dj;
    }

    @Override
    public double getDK() {
        return dk;
    }

    @Override
    public void setDK(double dk) {
        this.dk = dk;
    }

    @Override
    public IsDualQuaternion plus(IsDualQuaternion dualQuaternion) {
        return new DualQuaternion(this.rs + dualQuaternion.getRS(),
                this.ri + dualQuaternion.getRI(),
                this.rj + dualQuaternion.getRJ(),
                this.rk + dualQuaternion.getRK(),
                this.ds + dualQuaternion.getDS(),
                this.dk + dualQuaternion.getDI(),
                this.dj + dualQuaternion.getDJ(),
                this.dk + dualQuaternion.getDK()) {
        };
    }

    @Override
    public IsDualQuaternion times(IsDualQuaternion dualQuaternion) {
        /*
         * (a0 + b0i + c0j + d0k)(a1 + b1i + c1j + d1k)
         * (a0a1 - b0b1 - c0c1 - d0d1) +
         *   (a0b1 + b0a1 + c0d1 - d0c1)i +
         *   (a0c1 - b0d1 + c0a1 + d0b1)j +
         *   (a0d1 + b0c1 - c0b1 + d0a1)k
         * a0b1 = R(a0)R(b1) + R(a0)D(b1)epsilon + D(a0)R(b1)epsilon
         */
        double newRS = this.rs * dualQuaternion.getRS() -
                this.ri * dualQuaternion.getRI() -
                this.rj * dualQuaternion.getRJ() -
                this.rk * dualQuaternion.getRK();
        double newRI = this.rs * dualQuaternion.getRI() +
                this.ri * dualQuaternion.getRK() +
                this.rj * dualQuaternion.getRS() -
                this.rk * dualQuaternion.getRJ();
        double newRJ = this.rs * dualQuaternion.getRJ() -
                this.ri * dualQuaternion.getRK() +
                this.rj * dualQuaternion.getRS() +
                this.rk * dualQuaternion.getRI();
        double newRK = this.rs * dualQuaternion.getRK() +
                this.ri * dualQuaternion.getRJ() -
                this.rj * dualQuaternion.getRI() +
                this.rk * dualQuaternion.getRS();
        double newDS = this.rs * dualQuaternion.getDS() + this.ds * dualQuaternion.getRS() -
                this.ri * dualQuaternion.getDI() - this.di * dualQuaternion.getRI() -
                this.rj * dualQuaternion.getDJ() - this.dj * dualQuaternion.getRJ() -
                this.rk * dualQuaternion.getDK() - this.dk * dualQuaternion.getRK();
        double newDI = this.rs * dualQuaternion.getDI() + this.ds * dualQuaternion.getRI() +
                this.ri * dualQuaternion.getDK() + this.di * dualQuaternion.getRK() +
                this.rj * dualQuaternion.getDS() + this.dj * dualQuaternion.getRS() -
                this.rk * dualQuaternion.getDJ() - this.dk * dualQuaternion.getRJ();
        double newDJ = this.rs * dualQuaternion.getDJ() + this.ds * dualQuaternion.getRJ() -
                this.ri * dualQuaternion.getDK() - this.di * dualQuaternion.getRK() +
                this.rj * dualQuaternion.getDS() + this.dj * dualQuaternion.getRS() +
                this.rk * dualQuaternion.getDI() + this.dk * dualQuaternion.getRI();
        double newDK = this.rs * dualQuaternion.getDK() + this.ds * dualQuaternion.getRK() +
                this.ri * dualQuaternion.getDJ() + this.di * dualQuaternion.getRJ() -
                this.rj * dualQuaternion.getDI() - this.dj * dualQuaternion.getRI() +
                this.rk * dualQuaternion.getDS() + this.dk * dualQuaternion.getRS();
        return new DualQuaternion(newRS, newRI, newRJ, newRK,
                newDS, newDI, newDJ, newDK);
    }

    @Override
    public boolean equals(IsDualQuaternion dualQuaternion) {
        return this.rs == dualQuaternion.getRS() &&
        this.ri == dualQuaternion.getRI() &&
        this.rj == dualQuaternion.getRJ() &&
        this.rk == dualQuaternion.getRK() &&
        this.ds == dualQuaternion.getDS() &&
        this.di == dualQuaternion.getDI() &&
        this.dj == dualQuaternion.getDJ() &&
        this.dk == dualQuaternion.getDK();
    }
    public String toString(){
        return String.format("%+f %+fi %+fj %+fk %+fε %+fiε %+fjε %+fkε\n",
                this.rs, this.ri, this.rj, this.rk,
                this.ds, this.di, this.dj, this.dk);
    }
}