package leigh.astro.fits;

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * Utility methods for working with {@link AstroSub} objects.
 *
 * @author Jack Martin
 */
public class AstroSubUtil {

    /**
     * Attempt to locate up to <code>count</code> subs from the provided {@link List} of subs which were taken closest
     * in time to the provided <code>time</code>. A matching sub may be before, after, or on the provided time.
     */
    public List<AstroSub> findNearest(List<AstroSub> subs, Instant time, int count) {
        List<AstroSub> sortedSubs = new ArrayList<>();

        subs.sort(Comparator.comparing(astroSub -> Math.abs(Duration.between(astroSub.getTime(), time).toSeconds())));

        for (int i = 0; i < count && i < subs.size(); i++) {
            sortedSubs.add(subs.get(i));
        }

        return sortedSubs;
    }

    /**
     * Given a Light sub and a list of potential calibration subs, generate a list of calibrations which are related
     * to the light frame. A calibration frame is related if it matches, based on its type, the following rules:
     * <p>
     * Darks: A dark sub matches if the temperature, exposure length, gain, and offset settings are the same.
     * Flats: A flat sub matches if the filter is the same.
     * Bias: A bias sub matches if the temperature, gain and offset are the same.
     */
    public List<AstroSub> matchCalibrations(AstroSub light, List<AstroSub> calibrations) {
        ArrayList<AstroSub> matches = new ArrayList<>();

        for (AstroSub sub : calibrations) {
            switch (sub.getFrameType()) {
                case DARK:
                    if (sub.getCcdTemp() == light.getCcdTemp() && sub.getLengthSeconds() == light.getLengthSeconds()
                            && sub.getGain() == light.getGain() && sub.getOffset() == light.getOffset()) {
                        matches.add(sub);
                    }
                    break;
                case FLAT:
                    if (sub.getFilter().equals(light.getFilter())) {
                        matches.add(sub);
                    }
                    break;
                case BIAS:
                    if (sub.getCcdTemp() == light.getCcdTemp() && sub.getGain() == light.getGain()
                            && sub.getOffset() == light.getOffset()) {

                        matches.add(sub);
                    }
                    break;
            }
        }
        return matches;
    }

}