# ========================================================================================================
#
# John Pritchard
#
# Developed from esotk_fringe_obj_mask.py by Mark Neeser
#
# A python interactive window for use in the Austrian in-kind
# fringe-correction Reflex workflow.  This interactive window
# shows the results of the fringe-correction pipeline, allowing
# the User to compare the input image with the fringe-corrected
# image, and the fringe map.   From this interactive Actor the
# User can modify pipeline parameters and re-initiate the
# processing.
#
#
#
# ========================================================================================================

import os
import re
import sys
sys.path.append(os.path.dirname(__file__))
from esotk_giraf_gui import BaseDataPlotterManager, runInteractiveApp

try:
    # Import non-standard but needed modules. These must be as subset of what
    # the esotk_fringe_gui module tries to load.
    import reflex
    import pipeline_product
    import pipeline_display
    import matplotlib
    from giraf_plot_common import *

    class DataPlotterManager(BaseDataPlotterManager):

        # This function will read all the columns, images and whatever is needed
        # from the products. The variables , self.plot_x, self.plot_y, etc...
        # are used later in function plotProductsGraphics().
        def readFitsData(self, fitsFiles):
            
            # If fitsFiles doesn't have FF_PSFCENTROID, recipe must have failed, so search for tmp products...
            #Read all the products
            frames = dict()
            for frame in fitsFiles :
                if frame == '' :
                    continue
                category = frame.category
                frames[category] = frame
            self.have_ARC_RBNSTECTRA=True
            if not "ARC_RBNSPECTRA" in frames :
                self.have_ARC_RBNSTECTRA=False
                import glob
                for F in glob.glob('../../giwavecalibration_1/latest/*.fits') :
                    HDUlist=pyfits.open(F)
                    try :
                        fitsFiles.append(reflex.FitsFile(os.path.abspath(F), HDUlist[0].header['HIERARCH ESO PRO CATG'], None, None))
                    except :
                        pass
                    HDUlist.close()

            # Control variable to check if the interesting files were found in
            # the input.
            self.arc_frames = []
            self.science_frames = []
            self.raw_frames = []
            self.frameLabels = {}

            #Initialise the objects to read/display
            self.arc_rbnspectra     = None
            self.arc_raw = None
            self.objid = 1

            # Read all the products
            ff = {}
            for frame in fitsFiles:
                if frame == '':
                    continue
                category = frame.category
                if category == 'ARC_RBNSPECTRA':
                    self.frameLabels[frame.name]=frame.category+': '+frame.name
                    ff[frame.category]=frame
                    self.arc_rbnspectra   = frame
                elif category == 'ARC_SPECTRUM':
                    self.raw_frames.append(frame)
            if self.arc_rbnspectra is not None :
                self.science_frames.append(ff['ARC_RBNSPECTRA'])

            if self.arc_rbnspectra is not None :
                self.arc_rbnspectraPlot   = PlotableARC_RBNSPECTRA(self.arc_rbnspectra)

            self.science_found = len(self.science_frames) > 0
            self.raw_found = len(self.raw_frames) > 0

            self.DPR_CATG = "unknown"
            self.DPR_TYPE = "unknown"
            self.DPR_TECH = "unknown"
            if self.raw_found:
                HDUlist=pyfits.open(self.raw_frames[0].name)
                self.DPR_CATG = HDUlist[0].header['HIERARCH ESO DPR CATG']
                self.DPR_TYPE = HDUlist[0].header['HIERARCH ESO DPR TYPE']
                self.DPR_TECH = HDUlist[0].header['HIERARCH ESO DPR TECH']
                HDUlist.close()

            if self.science_found:
                self.esorex_log_file_name  = re.sub(".*/giraffe/" ,"../../", os.path.dirname(self.science_frames[0].name))+"/log_dir/esorex.log"

        def loadProducts(self, index):
            """
            Loading the plots...
            """
            super(DataPlotterManager, self).loadProducts(index)
            if self.arc_rbnspectra is not None :
                if self.science_frames[index].category == 'FF_PSFCENTROID' :
                    self.arc_rbnspectraPlot   = PlotableARC_RBNSPECTRA(self.arc_rbnspectra)
                
        # This function creates all the subplots. It is responsible for the
        # plotting layouts.
        # There can different layouts, depending on the availability of data
        # Note that subplot(I,J,K) means the Kth plot in a IxJ grid
        # Note also that the last one is actually a box with text, no graphs.
        def addSubplots(self, figure):
            self.list_subplot_image     = []
            if self.arc_rbnspectra is not None :
                gs = matplotlib.gridspec.GridSpec(100,1)
                self.subplot_arc_rbnspectra  = figure.add_subplot(gs[0:92,0])
                self.subplot_txtinfo         = figure.add_subplot(gs[95:100,0])
                self.setupFigure(figure)
            else :
                self.subtext_nodata      = figure.add_subplot(1,1,1)

        # This is the function that makes the plots.
        # Add new plots or delete them using the given scheme.
        # The data has been already stored in self.plot_x, self.plot_xdif, etc ...
        # It is mandatory to add a tooltip variable to each subplot.
        # One might be tempted to merge addSubplots() and plotProductsGraphics().
        # There is a reason not to do it: addSubplots() is called only once at
        # startup, while plotProductsGraphics() is called always there is a
        # resize.
        def plotProductsGraphics(self):

            if self.arc_rbnspectra is not None :

                self.plot_arc_rbnspectra()

                #Additional text info
                self.showTextInfo()

            else :
                #Data not found info
                self.showNoData()

        def plot_arc_rbnspectra(self) :
            title_arc_rbnspectra   = 'Wavelength calibration: Rebinned spectra [ARC_RBNSPECTRA] '
            tooltip_arc_rbnspectra = """Wavelength calibration: rebinned spectra.
Should be smooth."""
            self.arc_rbnspectraPlot.plot(self.subplot_arc_rbnspectra, title_arc_rbnspectra,
                             tooltip_arc_rbnspectra)

        def showTextInfo(self) :
            self.subplot_txtinfo.set_axis_off()
            try:
                mode = self.arc_rbnspectraPlot.rbnspectra.readKeyword('HIERARCH ESO INS SLITS ID')
            except:
                mode = 'unknown'
            try:
                filter_name = self.arc_rbnspectraPlot.rbnspectra.readKeyword('HIERARCH ESO INS FILT NAME')
            except:
                filter_name = 'unknown'
            try:
                grat_wlen = self.arc_rbnspectraPlot.rbnspectra.readKeyword('HIERARCH ESO INS GRAT WLEN')
            except:
                grat_wlen = 'unknown'
            try:
                raw1_name = self.arc_rbnspectraPlot.rbnspectra.readKeyword('HIERARCH ESO PRO REC1 RAW1 NAME')
            except:
                raw1_name = 'unknown'
            self.subplot_txtinfo.text(0.1, 0., 'DPid RAW1: %s\nDPR: %s :: %s :: %s\nMode/Setting/WLen: %s/%s/%s'
                               %(raw1_name,
                                 self.DPR_CATG,self.DPR_TYPE,self.DPR_TECH,
                                 mode,filter_name,str(grat_wlen)
                                ),
                               ha='left', va='top', weight='bold')

        def showNoData(self) :
            #Data not found info
            self.subtext_nodata.set_axis_off()
            self.text_nodata = 'Wave calibration data not found in the products\n(PRO.CATG=ARC_RBNSPECTRA)'
            self.subtext_nodata.text(0.1, 0.6, self.text_nodata, color='#11557c', fontsize=18,
                               ha='left', va='center', alpha=1.0)
            self.subtext_nodata.tooltip='ARC_RBNSPECTRA data not found in the products'


        def plotWidgets(self) :
            widgets = list()
            if False and self.arc_rbnspectra is not None :
                # Clickable subplot
                self.clickablesmapped = InteractiveClickableSubplot(
                       self.subplot_arc_rbnspectra, self.setExtractedObject)
                widgets.append(self.clickablesmapped)
            return widgets

        def setExtractedObject(self, point) :
            obj = self.arc_rbnspectra.getObjectInPosition(point.ydata)
            if obj != -1 :
                self.sci_extracted.selectObject(obj)
            self.plotSciExtracted()

    
        # This function specifies which are the parameters that should be presented
        # in the window to be edited.
        # Note that the parameter has to be also in the in_sop port (otherwise it
        # won't appear in the window)
        # The descriptions are used to show a tooltip. They should match one to one
        # with the parameter list
        # Note also that parameters have to be prefixed by the 'recipe name:'
        def setInteractiveParameters(self):
            paramList = list()
            paramList.append(reflex.RecipeParameter('giwavecalibration','bsremove-method',group='Bkg Sub',description='Backgruond subtraction method'))
            paramList.append(reflex.RecipeParameter('giwavecalibration','bsremove-yorder',group='Bkg Sub',description='Background subtraction yorder of 2-D polynomial fit'))
            paramList.append(reflex.RecipeParameter('giwavecalibration','wcal-lswidth',group='WCAL',description='List of window widths [pxl] used for line detection'))
            #paramList.append(reflex.RecipeParameter('giwavecalibration','wcal-slit',group='WCAL',description='Controls the slit geometry calibration'))
            return paramList

        def setWindowHelp(self):
            help_text = """
In this window, the user will interact with the GIRAF wavelength calibration reduction
"""
            return help_text

        def setWindowTitle(self):
            title = 'GIRAF Interactive wavecalibration reduction'
            return title

except ImportError:
    DataPlotterManager = None


if __name__ == '__main__':
    runInteractiveApp(DataPlotterManager)
