from __future__ import with_statement
from __future__ import absolute_import
from __future__ import print_function
import sys


try:
    import numpy
    import reflex
    from pipeline_product import PipelineProduct
    import pipeline_display
    import_success = True

except ImportError:
    import_success = False
    print("Error importing modules pyfits, wx, matplotlib, numpy")


def paragraph(text, width=None):
    """ wrap text string into paragraph
       text:  text to format, removes leading space and newlines
       width: if not None, wraps text, not recommended for tooltips as
              they are wrapped by wxWidgets by default
    """
    import textwrap
    if width is None:
        return textwrap.dedent(text).replace('\n', ' ').strip()
    else:
        return textwrap.fill(textwrap.dedent(text), width=width)


class DataPlotterManager(object):
    """
    This class must be added to the PipelineInteractiveApp with setPlotManager
    It must have following member functions which will be called by the app:
     - setInteractiveParameters(self)
     - readFitsData(self, fitsFiles):
     - addSubplots(self, figure):
     - plotProductsGraphics(self)
    Following members are optional:
     - setWindowHelp(self)
     - setWindowTitle(self)
    """

    # static members
    recipe_name = "vimos_ima_fringe"
    img_cat = "MASTER_FRINGE"

    def setInteractiveParameters(self):
        """
        This function specifies which are the parameters that should be presented
        in the window to be edited.  Note that the parameter has to also be 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.
        """
        return [
            reflex.RecipeParameter(recipe=self.recipe_name, displayName="chop_crud",
                                   group="vimos_ima_fringe", description="Chop crud method. <none | lowconf_block | hardcoded | lowconf_pix | hardconf_pix> [hardconf_pix]"),
            reflex.RecipeParameter(recipe=self.recipe_name, displayName="psm_ipix",
                                   group="vimos_ima_fringe", description="Minimum pixel area for each detected object. [5]"),
            reflex.RecipeParameter(recipe=self.recipe_name, displayName="psm_thresh",
                                   group="vimos_ima_fringe", description="Detection threshold in sigma above sky. [3.0]"),
            reflex.RecipeParameter(recipe=self.recipe_name, displayName="psm_nbsize",
                                   group="vimos_ima_fringe", description="Background smoothing box size. [64]"),
        ]

    def readFitsData(self, fitsFiles):
        """
        This function should be used to read and organize the raw fits files
        produced by the recipes.
        It receives as input a list of reflex.FitsFiles
        """
        # organize the files into a dictionary, here we assume we only have 
        # one file per category if there are more, one must use a
        # dictionary of lists
        self.frames = dict()
        for f in fitsFiles:
            self.frames[f.category] = PipelineProduct(f)

        # we only have two states, we have data or we don't
        # define the plotting functions we want to use for each
        if self.img_cat in self.frames:
            self.img_found = True
        else:
            self.img_found = False

    def addSubplots(self, figure):
        """
        This function should be used to setup the subplots of the gui.  The the
        matplotlib documentation for a description of subplots.
        """

        if self.img_found == True:
            self.img_plot1 = figure.add_subplot(2,2,1)
            self.img_plot2 = figure.add_subplot(2,2,2)
            self.img_plot3 = figure.add_subplot(2,2,3)
            self.img_plot4 = figure.add_subplot(2,2,4)
        else:
            self.img_plot = figure.add_subplot(111)

    def plotProductsGraphics(self):
        """
        This function should be used to plot the data onto the subplots.
        """
        if self.img_found == True:
            for n in range(1,5):
                par = "self.img_plot" + str(n)
                p = self.frames[self.img_cat]
                p.readImage(n)
                # setup the image display
                imgdisp = pipeline_display.ImageDisplay()
                imgdisp.setLabels('X', 'Y')
                tooltip = paragraph("""\
                Master Fringe image 
                """)

                chip_name = p.all_hdu[n].header['EXTNAME']

                if n ==1:
                    imgdisp.display(self.img_plot1, "Master Fringe {}".format(chip_name), tooltip, p.image)
                elif n == 2:
                    imgdisp.display(self.img_plot2, "Master Fringe {}".format(chip_name), tooltip, p.image)
                elif n == 3:
                    imgdisp.display(self.img_plot3, "Master Fringe {}".format(chip_name), tooltip, p.image)
                elif n == 4:
                    imgdisp.display(self.img_plot4, "Master Fringe {}".format(chip_name), tooltip, p.image)

        else:
            self.img_plot.set_axis_off()
            text_nodata = "Data not found. Input files should contain these" \
                           " types:\n%s" % self.img_cat
            self.img_plot.text(0.1, 0.6, text_nodata, color='#11557c',
                          fontsize=18, ha='left', va='center', alpha=1.0)
            self.img_plot.tooltip = 'No data found'

#This is the 'main' function
if __name__ == '__main__':
    from reflex_interactive_app import PipelineInteractiveApp

    # Create interactive application
    interactive_app = PipelineInteractiveApp()

    # get inputs from the command line
    interactive_app.parse_args()

    #Check if import failed or not
    if not import_success:
        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.set_continue_mode()

    #Print outputs. This is parsed by the Reflex python actor to
    #get the results. Do not remove
    interactive_app.print_outputs()
    sys.exit()
