package org.helioviewer.jhv.astronomy;

import java.nio.file.Path;
import java.util.List;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.helioviewer.jhv.JHVGlobals;
import org.helioviewer.jhv.log.Log;
import org.helioviewer.jhv.time.JHVTime;

import spice.basic.CSPICE;
import spice.basic.KernelDatabase;
import spice.basic.SpiceErrorException;

//import com.google.common.base.Stopwatch;

public class Spice {

    public static void loadKernels(List<String> files) {
        try {
            for (String f : files) {
                KernelDatabase.load(Path.of(JHVGlobals.dataCacheDir, f).toString());
            }
        } catch (Exception e) {
            Log.error(e);
        }
    }

    @Nullable
    public static String timeParse2UTC(String time) {
        try {
            return CSPICE.et2utc(CSPICE.str2et(time), "isoc", 0);
        } catch (SpiceErrorException e) {
            Log.error(e);
        }
        return null;
    }

    @Nullable
    static PositionCartesian[] getPositionRange(String observer, String target, String frame, long start, long end, long deltat) {
        // Stopwatch sw = Stopwatch.createStarted();
        try {
            long dt = deltat * 1000;
            PositionCartesian[] ret = new PositionCartesian[(int) ((end - start) / dt) + 1];
            int i = 0;
            for (long milli = start; milli <= end; milli += dt) {
                double[] v = positionRectangular(target, milli, frame, observer);
                ret[i++] = new PositionCartesian(milli, v[0], v[1], v[2]);
            }
            //System.out.println((sw.elapsed().toNanos() / 1e9));
            return ret;
        } catch (SpiceErrorException e) {
            Log.error(e);
        }
        return null;
    }

    @Nullable
    static Position getPositionLatitudinal(String observer, String target, String frame, JHVTime time) {
        try {
            double[] c = positionLatitudinal(target, time.milli, frame, observer);
            return new Position(time, c[0], c[1], c[2]);
        } catch (SpiceErrorException e) {
            Log.error(e);
        }
        return null;
    }

    @Nonnull
    public static Position getEarthCarrington(JHVTime time) {
        try {
            double[] c = positionLatitudinal("EARTH", time.milli, "SOLO_IAU_SUN_2009", "SUN");
            // like in SSW.getEarthSSW
            double lon = c[1];
            if (lon < 0)
                lon += 2 * Math.PI;
            return new Position(time, c[0], -lon, c[2]);
        } catch (Exception e) {
            Log.error(e);
        }
        return SSW.getEarthSSW(time);
    }

    private static final JHVTime J2000 = new JHVTime("2000-01-01T12:00:00");

    private static double milli2et(long milli) throws SpiceErrorException {
        double sec = (milli - J2000.milli) / 1000.;
        return sec + CSPICE.deltet(sec, "UTC");
    }

    private static long et2milli(double et) throws SpiceErrorException {
        double sec = et - CSPICE.deltet(et, "ET");
        return (long) (sec * 1000. + J2000.milli + .5);
    }

    private static double[] positionRectangular(String target, long milli, String frame, String observer) throws SpiceErrorException {
        double et = milli2et(milli);
        double[] lt = new double[1];
        double[] v = new double[3];
        CSPICE.spkpos(target, et, frame, "NONE", observer, v, lt);
        v[0] *= Sun.RadiusKMeterInv;
        v[1] *= Sun.RadiusKMeterInv;
        v[2] *= Sun.RadiusKMeterInv;
        return v;
    }

    private static double[] positionLatitudinal(String target, long milli, String frame, String observer) throws SpiceErrorException {
        return CSPICE.reclat(positionRectangular(target, milli, frame, observer));
    }

}

@@ -300,43 +300,8 @@
 CE;%0A
-import spice.basic.KernelDatabase;%0A
 impo
@@ -531,27 +531,21 @@
     
-KernelDatabase.load
+CSPICE.furnsh
 (Pat
@@ -613,32 +613,42 @@
        %7D catch (
+SpiceError
 Exception e) %7B%0A 

Use only CSPICE