/* ----------------------------------------
 * Origin  : GFI INFORMATIQUE 
 * Project : CDPP Propagation Tool 
 * ----------------------------------------
 * History 
 * Version : 01/05/2015 : SCA : V2.1
 * Version : 07/04/2016 : SCA : V2.2 (PSWS-H2020)
 * Version : 05/08/2024 : LBE : V2.11
 * DM-ID : Redmine#l0763 : 05/08/2024 : Field line added
 * ----------------------------------------
 */
package fr.tlse.irap.pt.client.controller.tools.carrington;

import fr.tlse.irap.fieldLine.FieldLine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.tlse.irap.pt.client.services.ServiceFactory;
import fr.tlse.irap.spaceElement.SpaceElement;
import fr.tlse.irap.tool.corotation.Corotation;
import fr.tlse.irap.tool.corotation.CorotationEnd;
import fr.tlse.irap.tool.radial.Radial;
import fr.tlse.irap.tool.sep.Sep;
import fr.tlse.irap.tool.sep.SepEnd;
import fr.tlse.irap.utils.CoordConverter;
import fr.tlse.irap.utils.ToolHelper;

public class CarringtonElement {

	protected static final Logger log = LoggerFactory.getLogger(CarringtonElement.class);

	public static enum ElementType {RADIAL, COROTATION, SEP;}
	private static Radial radial;
	private static Corotation corotation;
	private static Sep sep;

	private SpaceElement element;
	private ElementType type;
	private boolean computed = false;
	private double longitude;
	private double latitude;
        private FieldLine fieldLine;
	
	public CarringtonElement(SpaceElement e, ElementType type) {
		this.element = e;
		this.type = type;
	}

	public static void setRadialModel(Radial r) {
		radial = r;
	}

	public static void setCorotationModel(Corotation c) {
		corotation = c;
	}

	public static void setSepModel(Sep s) {
		sep = s;
	}

	/**
	 * Compute Carrington coordinates of space element at sun time using the current model algorithm 
	 */
	public void compute() {
		if (!computed) {
			try {
				switch (type) {
	            	case RADIAL:  
	            		computeRadial();
	            		break;
	            	case COROTATION:  
	            		computeCorotation();
	            		break;
	            	case SEP:  
	            		computeSep();
	            		break;
	            	default:
	            		break;
				}
				computed = true;
			} catch (Exception e) {
				log.warn("Error on compute Carrington coordinates for " + element.getName() + ". " + e.getMessage());
				//e.printStackTrace();
			}
		}
	}

	/**
	 * Compute Carrington coordinates of space element at start time 
	 * AttitudeSun is already computed from start time
	 */
	private void computeRadial() {
		//log.debug("COMPUTE CARRINGTON POSITION");
		double[] longLat = CarringtonHelper.computeCarringtonCoordinates(element, radial.getStartTime().getTime(), radial.getSunAttitudeTSun());
		if (longLat != null) {
			longitude = longLat[0];
			latitude = longLat[1];
		}
	}

	/**
	 * Compute Carrington coordinates of a space element at final time using corotation propagation
	 */
	private void computeCorotation() {
		// call web service that compute propagation
		CorotationEnd cEnd = ServiceFactory.getToolService().computeCorotation(corotation, element);
		
		// compute carrington coordinates of end at final time 
		if (cEnd.isSun()) {
			longitude = 0;
			latitude = 0;
		}
		else {
			double[] longLat = CarringtonHelper.computeCarringtonCoordinates(cEnd.getEndSource(), cEnd.getEndTime().getTime(), false);
			if (longLat != null) {
				double omega = Math.toDegrees(ToolHelper.getRotationFrequency(corotation.getRotationPeriod()));
				double distEndFinalTXY = ToolHelper.computeRadialDistanceXY(cEnd.getEndSource());
				//double distEndFinalTXY = ToolHelper.computeRadialDistanceXY(src) * Math.cos(Math.toRadians(longLat[1]);
				// compute delta longitude between END and spiral footpoint
				double dPhi = (distEndFinalTXY * omega) / corotation.getSpeedSolarWind();
				// set the carrington end source coordinates 
				longitude = CoordConverter.normalizeLongitude(longLat[0] + dPhi);
				latitude = longLat[1];
			}
		}
	}

	/**
	 * Compute SEP coordinates of space element at final time using SEP propagation 
	 */
	private void computeSep() {
		// call web service that compute propagation
		SepEnd sepEnd = ServiceFactory.getToolService().computeSep(sep, element);

		// compute carrington coordinates of end at final time 
		if (sepEnd.isSun()) {
			longitude = 0;
			latitude = 0;
		}
		else {
			double[] longLat = CarringtonHelper.computeCarringtonCoordinates(sepEnd.getEndSource(), sepEnd.getEndTime().getTime(), false);
			if (longLat != null) {
				double omega = Math.toDegrees(ToolHelper.getRotationFrequency(sep.getRotationPeriod()));
				double distEndFinalTXY = ToolHelper.computeRadialDistanceXY(sepEnd.getEndSource());
				//double distEndFinalTXY = ToolHelper.computeRadialDistanceXY(src) * Math.cos(Math.toRadians(longLat[1]);
				// compute delta longitude between END and spiral footpoint
				double dPhi = (distEndFinalTXY * omega) / sep.getSpeedSolarWind();
				// set the carrington end source coordinates 
				longitude = CoordConverter.normalizeLongitude(longLat[0] + dPhi);
				latitude = longLat[1];
			}
		}
	}

	public SpaceElement getElement() {
		return element;
	}
	
	public void setElement(SpaceElement e) {
		this.element = e;
	}
	
	public boolean isComputed() {
		return computed;
	}
	
	public void setComputed(boolean computed) {
		this.computed = computed;
	}
	
	public double getLongitude() {
		return longitude;
	}
	
	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}
	
	public double getLatitude() {
		return latitude;
	}
	
	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	public String getName(){
		return element.getName();
	}

	public ElementType getType(){
		return type;
	}

    /**
     * @return the fieldLine
     */
    public FieldLine getFieldLine() {
        return fieldLine;
    }

    /**
     * @param fieldLine the fieldLine to set
     */
    public void setFieldLine(FieldLine fieldLine) {
        this.fieldLine = fieldLine;
    }

}
