# import the needed modules
try:
  import reflex
  import matplotlib.gridspec
  import_sucess = True

#NOTE for developers: 
# -If you want to modify the current script to cope
#  with different parameters, this is the function to modify:
#  setInteractiveParameters()
# -If you want to modify the current script to read different data from
#  the input FITS, this is the function to modify:
#  readFitsData()                  (from class DataPlotterManager) 
# -If you want to modify the current script to modify the plots (using the same
#  data),  this is the function to modify:
#  plotProductsGraphics()          (from class DataPlotterManager)
# -If you want to modify the text that appears in the "Help" button,
#  this is the function to modify:
#  setWindowHelp()
# -If you want to modify the title of the window, modify this function:
#  setWindowTitle()


  #This class deals with the specific details of data reading and final plotting.
  class DataPlotterManager:
    # 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().
    # Add/delete these variables as you need (only that plotProductsGraphics()
    # has to use the same names).
    # You can also create some additional variables (like statistics) after
    # reading the files.
    # If you use a control variable (self.xxx_found), you can modify 
    # later on the layout of the plotting window based on the presence of 
    # given input files. 
    # sof contains all the set of frames
    def readFitsData(self, fitsFiles):
      import os.path, glob
      for F in glob.glob('../../giscience_1/latest/*.fits') :
          HDUlist=pyfits.open(F)
          fitsFiles.append(reflex.FitsFile(os.path.abspath(F), HDUlist[0].header['HIERARCH ESO PRO CATG'], None, None))
          HDUlist.close()

      #Initialise the objects to read/display
      self.sci_rbnspectra     = None
      self.fibid = 1

      #Read all the products
      frames = dict()
      for frame in fitsFiles :
        if frame == '' :
          continue
        category = frame.category
        frames[category] = frame

      #for inst_mode in ('MEDUSA', 'IFU', 'ARGUS') :
      if 'SCIENCE_RBNSPECTRA' in frames:
          self.sci_rbnspectra        = PlotableSCI_RBNSPECTRA(frames["SCIENCE_RBNSPECTRA"])
          self.sci_rbnspectra_extr   = PlotableExtractedScience(frames["SCIENCE_RBNSPECTRA"])
          if 'SCIENCE' in frames:
              self.ff_raw = frames['SCIENCE']
              HDUlist=pyfits.open(self.ff_raw.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()

    # 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):
      if self.sci_rbnspectra is not None :
          gs = matplotlib.gridspec.GridSpec(100,1)
          self.subplot_sci_rbnspectra       = figure.add_subplot(gs[0:62,0])
          self.subplot_sci_rbnspectra_extr  = figure.add_subplot(gs[70:92,0])
          self.subplot_txtinfo       = figure.add_subplot(gs[95:100,0])
      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.sci_rbnspectra is not None :

        self.plot_sci_rbnspectra()
        self.plot_sci_rbnspectra_extr()

        #Additional text info
        self.showTextInfo()

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

    def plot_sci_rbnspectra(self) :
        title_sci_rbnspectra   = 'Science: Rebinned spectra [SCIENCE_RBNSPECTRA]\nCosmic Ray cleaning: %s' %(self.sci_rbnspectra.rbnspectra.readKeyword('CMETHOD'))
        tooltip_sci_rbnspectra = """Science: rebinned spectra."""
        self.sci_rbnspectra.plot(self.subplot_sci_rbnspectra, title_sci_rbnspectra,
                             tooltip_sci_rbnspectra)

    def plot_sci_rbnspectra_extr(self) :
        title_sci_rbnspectra_extr   = 'Rebinned spectra of OBJECT, S/N = 0.'
        tooltip_sci_rbnspectra_extr = """Science: rebinned spectra."""
        self.sci_rbnspectra_extr.plot(self.subplot_sci_rbnspectra_extr, title_sci_rbnspectra_extr,
                             tooltip_sci_rbnspectra_extr)

    def showTextInfo(self) :
      self.subplot_txtinfo.set_axis_off()
      try:
        mode = self.sci_rbnspectra.rbnspectra.readKeyword('HIERARCH ESO INS SLITS ID')
      except:
        mode = 'unknown'
      try:
        filter_name = self.sci_rbnspectra.rbnspectra.readKeyword('HIERARCH ESO INS FILT NAME')
      except:
        filter_name = 'unknown'
      try:
        grat_wlen = self.sci_rbnspectra.rbnspectra.readKeyword('HIERARCH ESO INS GRAT WLEN')
      except:
        grat_wlen = 'unknown'
      try:
        raw1_name = self.sci_rbnspectra.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')
      try:
        slit = self.sci_extracted.extractedscience.readKeyword('HIERARCH ESO INS SLIT NAME')
        self.subplot_txtinfo.text(0.5, 0., 'Slit name (LSS): '+slit, 
                               ha='left', va='center', weight='bold')
      except:
        pass
      try:
        checksum = self.sci_extracted.extractedscience.readKeyword('HIERARCH ESO INS MOS CHECKSUM')
        self.subplot_txtinfo.text(0.5, 0., 'Slits checksum (MOS): '+str(checksum), 
                               ha='left', va='center', weight='bold')
      except:
        pass
      try:
        mask_id = self.sci_extracted.extractedscience.readKeyword('HIERARCH ESO INS MASK ID')
        self.subplot_txtinfo.text(0.5, 0., 'Mask id (MXU): '+mask_id, 
                               ha='left', va='center', weight='bold')
      except:
        pass
      try:
        target_name = self.sci_extracted.extractedscience.readKeyword('HIERARCH ESO OBS TARG NAME')
        self.subplot_txtinfo.text(0.1, 0.6, 'Target name: '+target_name, 
                               ha='left', va='center', weight='bold')
      except:
        pass

    def showNoData(self) :
      #Data not found info
      self.subtext_nodata.set_axis_off()
      self.text_nodata = 'Science data not found in the products (PRO.CATG=SCIENCE_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='Science data not found in the products'

    def plotWidgets(self) :
      widgets = list()
      if self.sci_rbnspectra is not None :
        # Clickable subplot
        self.clickablesmapped = InteractiveClickableSubplot(
          self.subplot_sci_rbnspectra, self.setExtractedObject)
        widgets.append(self.clickablesmapped)
      return widgets

    def setExtractedObject(self, point) :
        obj = self.sci_rbnspectra.getObjectInPosition(point.xdata+0.5)
        if obj != -1 :
            self.sci_rbnspectra_extr.selectObject(obj)
        self.plot_sci_rbnspectra_extr()

                
    # 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('giscience','bsremove-method',group='Bkg Sub',description='Backgruond subtraction method'))
      paramList.append(reflex.RecipeParameter('giscience','bsremove-yorder',group='Bkg Sub',description='Background subtraction yorder of 2-D polynomial fit'))
      paramList.append(reflex.RecipeParameter('giscience','extr-method',group='Extr',description="Extraction method: 'SUM', 'HORNE' or 'OPTIMAL'. <SUM | OPTIMAL | HORNE> [SUM]"))
      paramList.append(reflex.RecipeParameter('giscience','flat-apply',group='Flat',description="Apply or not the flat field correction. [TRUE]"))


      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:
  import_sucess = 'false'
  print "Error importing modules pyfits, wx, matplotlib, numpy"

#This is the 'main' function
if __name__ == '__main__':

  # import reflex modules
  import reflex_interactive_app
  import sys

  # import GIRAF reflex modules
  from giraf_plot_common import *

  # Create interactive application
  interactive_app = reflex_interactive_app.PipelineInteractiveApp(enable_init_sop=True)

  #Check if import failed or not
  if import_sucess == 'false' :
    interactive_app.setEnableGUI('false')

  #Open the interactive window if enabled
  if interactive_app.isGUIEnabled() :
    #Get the specific functions for this window
    dataPlotManager = DataPlotterManager()
    interactive_app.setPlotManager(dataPlotManager)
    interactive_app.showGUI()
  else :
    interactive_app.passProductsThrough()

  # print outputs
  interactive_app.print_outputs()

  sys.exit()
