/* ----------------------------------------
 * 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
 * ----------------------------------------
 */
package fr.tlse.irap.shock;

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

import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Shockwave3dEvent {

    /**
     * List of timed shockwave values in event
     */
    private List<Shockwave3d> shockwaves = new ArrayList<Shockwave3d>();
    /**
     * Time event as it is set in folder name
     */
    private Date time = null;
    
    /**
     * Contains list of min and max for each parameter
     */
    private List<double[]> minMaxList = new ArrayList<double[]>();

    public Shockwave3dEvent() {
    }

    public void addShockwave(Shockwave3d pObj) {
        shockwaves.add(pObj);
    }

    public Shockwave3d getNearestFromTime(Date date) {
        //if (shocks.isEmpty() || date.before(shocks.get(0).getShockTime())) {
        if (shockwaves.isEmpty() || shockwaves.size() < 2) {
            return null;
        }
        Shockwave3d prev = (shockwaves.get(0));
        Shockwave3d next = null;

        for (Shockwave3d shock : shockwaves) {
            if (shock.getTime().after(date)) {
                next = shock;
                break;
            }
            prev = shock;
        }

        if (next != null) {
            long deltaPrev = Math.abs(prev.getTime().getTime() - date.getTime());
            long deltaNext = Math.abs(next.getTime().getTime() - date.getTime());
            long deltaTime = shockwaves.get(1).getTime().getTime() - shockwaves.get(0).getTime().getTime();

            if (deltaPrev < deltaNext) {
                if (deltaPrev < deltaTime) {
                    return prev;
                }
            } else {
                if (deltaNext < deltaTime) {
                    return next;
                }
            }
        }
        // in other cases return null
        return null;
    }
    
    public void computeMinMax() {
        int lIdx = 0;
        for(Shockwave3d lS3d:shockwaves) {
            if(lIdx==0) {
                //At first, init min/max/array
                minMaxList.clear();
                if(!lS3d.getParameters().isEmpty()) {
                    for(double lVal: lS3d.getParameters().get(0)) {
                        minMaxList.add(new double[]{lVal,lVal});
                    }
                }
            }else {
                if(!lS3d.getParameters().isEmpty()) {
                    for(double[] lVal: lS3d.getParameters()) {
                        for(int i=0;i<lVal.length;i++) {
                            if(minMaxList.get(i)[0]>lVal[i]) minMaxList.get(i)[0]=lVal[i];//min
                            if(minMaxList.get(i)[1]<lVal[i]) minMaxList.get(i)[1]=lVal[i];//max
                        }
                    }
                }
            }
            lIdx++;
        }
    }
    
    

    /**
     * Time event as it is set in folder name
     * @return the time
     */
    public Date getTime() {
        return time;
    }

    /**
     * Time event as it is set in folder name
     * @param time the time to set
     */
    public void setTime(Date time) {
        this.time = time;
    }

    /**
     * List of timed shockwave values in event
     * @return the shockwaves
     */
    public List<Shockwave3d> getShockwaves() {
        return shockwaves;
    }

    /**
     * List of timed shockwave values in event
     * @param shockwaves the shockwaves to set
     */
    public void setShockwaves(List<Shockwave3d> shockwaves) {
        this.shockwaves = shockwaves;
    }

    /**
     * Contains list of min and max for each parameter
     * @return the minMaxList
     */
    public List<double[]> getMinMaxList() {
        return minMaxList;
    }

    /**
     * Contains list of min and max for each parameter
     * @param minMaxList the minMaxList to set
     */
    public void setMinMaxList(List<double[]> minMaxList) {
        this.minMaxList = minMaxList;
    }

}
