#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# System modules
from time import sleep
from astropy.time import Time

# Third-party modules
import gnuplotlib as gp
import numpy as np
from astropy.io import fits

# Custom modules
from config.constants import pixscale, temp_fits
from devices import cam, foc
from utils.analysis import fit_star
from utils.logger import log
from directory.structure import foc_path

# Other templates
from templates.basetemplate import BaseTemplate
from templates.box import Template as Box


class Template(BaseTemplate):
    def __init__(self):
        super().__init__()
        self.name = "focus"
        self.description = "Fit boxed images to get optimal focus"

    def content(self, params):

        ########################
        ##### Params check #####
        ########################

        try:
            objname = params.get("object") or "test"
            filt = params["filter"]
            binning = params["binning"]
            exptime = params["exptime"]
            center = params.get("center") or cam.center
            width = params.get("width") or 400//binning
            height = params.get("height") or 400//binning
            repeat = params.get("repeat") or 10
            step = params.get("step") or 10

        except KeyError as e:
            msg = f"Parameter {e} not found"
            log.error(msg)
            self.error.append(msg)
            return

        # for Box
        fixed = {
            "objname": objname,
            "repeat": 1,
            "center": center,
            "width": width,
            "height": height,
        }
        params.update(fixed)

        #######################################
        ##### Preparing to the focus loop #####
        #######################################

        # Getting initial focus
        original_foc = foc.position

        #starting from half before
        total_lenght = step*repeat
        foc.position -= total_lenght/2

        # Preparing empty arrays for values
        m2_arr = np.array([], dtype=int)
        fwhm_arr = np.array([])
        self.output = []            
        
        # Preparing the focus file path
        now = Time.now().isot
        file_path = foc_path(now)
        
        # Initial comment about variables a, b, c
        comment1 = f"Focus procedure of {now}"
        comment2 = f"rep m2[µm] fwhm[px]"
        
        # Write the initial comment if the file doesn't exist
        with open(file_path, "a+") as file:
            log.info(f"Init file {file_path}")
            file.seek(0)
            if not file.read(1):
                file.write(f"# {comment1}\n")
                file.write(f"# {comment2}\n")
        
        # Instanciating a Box template
        box = Box()

        for rep in range(0, repeat):
            log.info(f"Step {rep} of {repeat-1}")

            ################################
            ##### Taking a boxed image #####
            ################################

            box.run(params)  # saves temp.fits boxed image

            data = fits.getdata(temp_fits)

            ###############################
            ##### Fitting a 2d Moffat #####
            ###############################

            fitted = fit_star(data, model="moffat")

            ##############################
            ##### Filling the arrays #####
            ##############################
            
            m2 = foc.position
            fwhm = fitted.fwhm*pixscale*binning

            m2_arr = np.append(m2_arr, m2)
            fwhm_arr = np.append(fwhm_arr, fwhm)
            
            y, x = np.indices(data.shape)
            self.output = {
                "focus": {
                    "m2" : m2_arr.tolist(),
                    "fwhm": fwhm_arr.tolist(),
                },
                # "data": data.tolist(),
                # "fit": fitted(x,y).tolist(),
                # "residuals": np.round( data - fitted(x,y) , 1).tolist(),
            }
            
            # log.debug(self.output)
            # log.info(f"Found: focus={m2}µm, FWHM={fwhm}'' ")
            
            # opening all the time and not at begginning just for safety
            with open(file_path, "a") as file:
                msg = f"{rep:>3} {m2:>10} {fwhm:>10} "
                file.write(msg+"\n")
                log.info("Writing: "+msg)
            
            ######################
            ##### Moving M2  #####
            ######################

            foc.position += step
            log.warning(f"Moving focus py {step}µm, to {foc.position}µm")
            sleep(0.3)

        ##############################
        ##### Showing the result #####
        ##############################

        log.info(f"focus={m2_arr}")
        log.info(f"fwhm={fwhm_arr}")
        
        gp.plot((m2_arr, fwhm_arr),
                unset="grid",
                _with="linespoints",
                terminal='dumb 90 30',
                xlabel="x=focus [µm], y=fwhm ['']")        
        
        #################################
        ##### Back to initial focus #####
        #################################

        log.info("Setting back original focus")
        foc.position = original_foc
