
from shinsapp import SHINSApp
from util.shinsLogger import logger
from util import variables as uvars
from util import functions as ufun
from util import exception
import numpy as np

from SHARKNIR_gen_base import SHARKNIR_gen_base

class SHARKNIR_cal_tec_NCPA_PD_argos(SHINSApp):

    @exception.handler_for_run
    def run(self, ins_s=None, det_s=None, tel_s=None, rtc_s=None, **kwargs):
        '''Calculate NCPA with PD using star.
        '''

        logger.info(__name__)
        self.status = uvars.EXIT_SUCCESS
        obsController = self.obsController

        self.gen_base = SHARKNIR_gen_base();        gen_base = self.gen_base

        fitsDir = uvars.fitsDir + obsController.getCurrentDataDirectory() +'/'

        #############################################
        # START AND WAIT INSTRUMENT AND SASHA SETUP #
        #############################################

        gen_base.main(ins_s=ins_s, det_s=det_s, expose=False)

        self.master_array = [] # the list of images CDS-subtracted and meaned over NREADS=10

        ##########################
        # OPEN REAL-TIME TT LOOP #
        ##########################
        if self.paragraph("OPEN REAL-TIME TT LOOP"):
            logger.info("TT open loop")
            self.status = obsController.RTCTTOpenLoop()
            ufun.error_handler(self.status, "RTCTTOpenLoop")
            logger.debug(self.status)
            logger.info("Tip tilt loop open on TECCAM")
        
        # Apo positions are shared between focus and defocus loops
        several_apos = ["HOLE3", "Lens_PD_neg", "Lens_PD_pos"]

        #############################
        # First LOOP (FOCUSED STAR) #
        ##############################

        #several_drops = ["68", "417", "417"]
        several_drops = ["0", "85", "85"]

        logger.info("***Starting Focused star")

        for apo, drop in zip(several_apos, several_drops):

            ins_s = {
                "APODIZER_W": apo,
            }
            
            det_s["NDROPS"] = drop
            
            logger.info("****Start focus setup and image")
            self.status, self.filename, self.other = gen_base.main(ins_s, det_s, **kwargs)
            logger.info("****End focus setup and image")

            if self.paragraph("Focused {}".format(apo)):
                
                self.master_array = ufun.ncpa_masterize(fitsDir, self.filename, self.master_array)

#        ##################
#        # PAUSE / RESUME #
#        ##################

#        self.paused = True
#        logger.warning("Resume when ready")
#        self.check_pause_or_abort()

        ############################
        # APPLY 3mm OFFSET ON SOUL #
        ############################


        deltaZ = -3
        logger.info("Moving SOUL with an offset of {} mm ...".format(deltaZ))
        self.obsController.OffsetZAO(+deltaZ, "LEFT")
        logger.info("Moving SOUL with an offset of {} mm ... DONE".format(deltaZ))

        
        ################################
        # Second LOOP (DEFOCUSED STAR) #
        ################################

        #several_drops = ["137", "0", "137"]
        several_drops = ["21", "200", "35"]

        logger.warning("Starting Defocused star")
        for apo, drop in zip(several_apos, several_drops):

            ins_s = {
                "APODIZER_W": apo,
            }
            
            det_s["NDROPS"] = drop
            
            logger.info("****Start defocus setup and image")
            self.status, self.filename, self.other = gen_base.main(ins_s, det_s)
            logger.info("****End defocus setup and image")
            
            if self.paragraph("Defocused {}".format(apo)):
                
                self.master_array = ufun.ncpa_masterize(fitsDir, self.filename, self.master_array)

        ########################################
        # ONERA CODE in IDL, using IDL bridges #
        ########################################            
        if self.paragraph("ONERA processing"):
            wvl = determine_filter_wavelength(sci1 = ins_s["SCI_FILT_W1"] , sci2 = ins_s["SCI_FILT_W2"])
            zernikes = ufun.call_onera(self.master_array, wavelength=wvl)


        ###################
        # Calculate modes #
        ###################
        if self.paragraph("Calculate modes modes"):

            logger.info("Found these zernikes:")
            logger.info(str(zernikes))

            modes = ufun.zernikes_to_modes(zernikes)

            logger.info("Function zernike_to_modes returns:")
            logger.info(str(modes))


        ############################
        # MOVING BACK SOUL TO -3mm #
        ############################

            
        logger.info("Moving SOUL back where at the begining of template ...")
        self.obsController.OffsetZAO(-deltaZ, "LEFT")
        logger.info("Moving SOUL back where at the begining of template ... DONE")

        self.paused = True
        logger.warning("Resume if you agree to apply; Quit otherwise.")
        print("(R)esume, (Q)uit")
        import sys
        from select import select
        
        timeout = 2
               
        answer = None
        print("Enter something:"),
        self.paused = True
        
        
        while self.paused==True and self.aborted==False:

            rlist, _, _ = select([sys.stdin], [], [], timeout)
            if rlist:
                answer = sys.stdin.readline()
                print(answer)
            else:
                print("still waiting...")

            if answer:
                if answer.lower().startswith('r'):
                    self.paused = False
                    pass
                if answer.lower().startswith('q'):
                    self.paused = False
                    self.aborted = True
                    self.abort()
                    return
                else:
                    pass

            
        ###############
        # Apply Modes #
        ###############
        
        reserved = [0,0]
        zeros = [0,0,0,0]

        logger.info("Upload a mode vector to internal DM")
        self.status = obsController.RTCTTModeUpload(reserved+zeros+modes, absolute=False)
        logger.info("Waiting setup to apply displacement... DONE")
        
