package leigh.astro.app;

import leigh.astro.catalog.CatalogObject;
import leigh.astro.catalog.StellarCatalog;
import leigh.astro.fits.AstroSub;
import leigh.astro.fits.AstroSubType;
import leigh.astro.fits.FitsScanner;
import leigh.astro.iraf.Photometry;
import leigh.mecha.lang.Counter;
import leigh.mecha.lang.CountingList;
import leigh.mecha.log.MechaLogger;
import leigh.mecha.log.MechaLoggerFactory;
import leigh.mecha.util.UniversalJob;
import leigh.mecha.util.VelocityWatch;

import java.io.IOException;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Development utility for producing various test reports on a FITS file repo.
 *
 * @author Alex Leigh
 */
public class FitsListApp {
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(FitsListApp.class);

    public static void main(String[] args) throws Exception {
        if (args.length != 1) {
            logger.info("Usage: FitsListApp path");
            System.exit(UniversalJob.RET_BADARGS);
        }

        FitsScanner fs = new FitsScanner();
        List<AstroSub> allSubs = fs.scanPath(Paths.get(args[0]));

        StellarCatalog catalog = new StellarCatalog();

        Counter c = new Counter<CatalogObject>();
        for (AstroSub sub : allSubs) {
            if (sub.getFrameType() == AstroSubType.LIGHT) {
                List<CatalogObject> objs = sub.contains(catalog.getObjects());
                c.count(objs);
            }
        }

        c.print(logger);
    }

    private static void process(List<AstroSub> allSubs) throws IOException {
        CountingList<String> filterTime = new CountingList<>();
        CountingList<String> temps = new CountingList<>();
        StellarCatalog catalog = new StellarCatalog();
        CatalogObject obj = catalog.get("NGC6888");
        List<AstroSub> subs = new ArrayList<>();
        for (AstroSub sub : allSubs) {
            if (sub.getObj().isNear(obj.getJ2000Coordinate())) {
                subs.add(sub);
            }
        }

        double len = 0;
        int light = 0;
        int bias = 0;
        int dark = 0;
        int flat = 0;

        for (AstroSub sub : subs) {
            len += sub.getLengthSeconds();
            filterTime.increment(sub.getFilter(), (int) sub.getLengthSeconds());
            temps.increment(Double.toString(sub.getCcdTemp()), 1);
            switch (sub.getFrameType()) {
                case BIAS:
                    bias++;
                    break;
                case LIGHT:
                    light++;
                    break;
                case DARK:
                    dark++;
                    break;
                case FLAT:
                    flat++;
                    break;
            }
        }

        logger.info("Subs: [cnt: {}] [len: {}] [light: {}] [dark: {}] [bias: {}] [flat: {}]",
                subs.size(),
                Duration.ofSeconds((long) len),
                bias, light, dark, flat);

        for (Map.Entry<String, Integer> filters : filterTime.getCounts().entrySet()) {
            logger.info("Filter: [name: {}] [len: {}]", filters.getKey(), Duration.ofSeconds(filters.getValue()));
        }

        for (Map.Entry<String, Integer> temp : temps.getCounts().entrySet()) {
            logger.info("Temp: [ccd: {}] [qty: {}]", temp.getKey(), temp.getValue());
        }

        ExecutorService executor = Executors.newFixedThreadPool(8);

        VelocityWatch vw = new VelocityWatch(logger);

        for (AstroSub sub : subs) {
            if (sub.getFrameType() == AstroSubType.LIGHT && sub.getFilter().equals("H_Alpha")) {
                executor.submit(() -> {
                    try {
                        Photometry pm = sub.getPhotometry();

                        logger.info("sub [id: {}] [fwhm: {}] [stars: {}] [sharp: {}] [round: {}]",
                                sub.getId(), pm.averageFWHM(), pm.getCount(), pm.averageSharp(), pm.averageRound());

                        if (pm.averageHWHM() > 2.0) {

                            vw.event("bad");
                        } else {
                            vw.event("good");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            }
        }

        executor.shutdown();
    }
}