/* ----------------------------------------
 * Origin  : GFI INFORMATIQUE 
 * Project : CDPP Propagation Tool 
 * ----------------------------------------
 * History 
 * Version : 06/04/2023 : LBE : V2.7
 * DM-ID : redmine#8642 : 06/04/2023 : Added 3D shockwave
 * Version : 12/09/2023 : LBE : V2.8
 * DM-ID : Redmine#11197 : 12/09/2023 : 3DShocks improvments
 * ----------------------------------------
 */
package fr.tlse.irap.shock;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Shockwave3d implements Serializable, Comparable<Shockwave3d> {

    private static final long serialVersionUID = 1L;

    private final int SPEED_POS = 0;
    private final int ALFVEN_POS = 1;
    private final int FM_POS = 2;
    private final int COMP_POS = 3;
    private final int THETA_BN_POS = 4;

    /**shock date*/
    private Date time;
    /**positions x/y/z in km*/
    private List<double[]> positions;
    /**speed, parameters, ...*/
    private List<double[]> parameters;
    /** farthest point from center index */
    private int noseIdx = -1;

    public Shockwave3d() {
        positions = new ArrayList<double[]>();
        parameters = new ArrayList<double[]>();
    }

    /**
     * @return the shockTime
     */
    public Date getTime() {
        return time;
    }

    /**
     * @param shockTime the shockTime to set
     */
    public void setTime(Date shockTime) {
        this.time = shockTime;
    }

    /**
     * @return the positions
     */
    public List<double[]> getPositions() {
        return positions;
    }

    /**
     * @param positions the positions to set
     */
    public void setPositions(List<double[]> positions) {
        this.positions = positions;
        noseIdx = findSwNose();
    }

    /**
     * @return the parameters
     */
    public List<double[]> getParameters() {
        return parameters;
    }

    /**
     * @param parameters the parameters to set
     */
    public void setParameters(List<double[]> parameters) {
        this.parameters = parameters;
    }

    @Override
    public int compareTo(Shockwave3d pSw3d) {
        if(time.before(pSw3d.getTime())) {
            return -1;
        }
        if(time.after(pSw3d.getTime())) {
            return 1;
        }
        return 0;
    }

    
    /**
     * Get farthest point of a shockwave.
     * @param pSw3d
     * @return max point
     */
    private int findSwNose() {
        double lMax=0;
        int lMaxPosIdx = 0;
        for (int i = 0; i < positions.size(); i++) {
            double[] lPos = positions.get(i);
            double lMagnitude = Math.sqrt(lPos[0]*lPos[0]+lPos[1]*lPos[1]+lPos[2]*lPos[2]);
            if(lMagnitude>lMax) {
                lMax=lMagnitude;
                lMaxPosIdx = i;
                //System.out.println("Max mag = "+lMagnitude);
            }
        }
        return lMaxPosIdx;
    }
    
    /**
     * Get nose distance
     * @return 
     */
    public double getNoseDist() {
        if (noseIdx < 0) {
            noseIdx = findSwNose();
        }
        double[] lPos = positions.get(noseIdx);
        return Math.sqrt(lPos[0] * lPos[0] + lPos[1] * lPos[1] + lPos[2] * lPos[2]);
    }
    
    /**
     * Get nose position
     * @return x/y/z position in km in carrington coordinates
     */
    public double[] getNosePos() {
        if (noseIdx < 0) {
            noseIdx = findSwNose();
        }
        return positions.get(noseIdx);
    }
    
    
}
