#! /usr/bin/env python3
# -*- coding: iso-8859-15 -*-

import matplotlib as mpl
mpl.use('Agg') # necessary to be able to generate the reports even without X server
import matplotlib.pyplot as plt

import datetime
import numpy as np
from . import gravi_visual_class
        
#==============================================================================
# Preparation of the report using reportlab
#==============================================================================
def produce_dark_report(dark,filename):
    # From gravi_visual_class
    from . import gravi_visual_class
    from .gravi_visual_class import myFirstPage, myLaterPages, styles
    from .gravi_visual_class import clipdata, transbarchartout, graphoutaxes, graphoutnoaxis
    from .gravi_visual_class import graphoutnoxaxes, graphscatteraxes, graphaxesplt
    from .gravi_visual_class import plotTitle, plotSubtitle
    from .gravi_visual_class import get_key_withdefault, create_array_from_list, baseline_phases
    from .gravi_visual_class import mean_angle, std_angle, clean_unwrap_phase, nanaverage
    from .gravi_visual_class import clean_gdelay_is, clean_gdelay_fft, clean_gdelay_full
    from .gravi_visual_class import base_list, tel_list, nbase, ntel
    from .gravi_visual_class import plotReductionSummary, plotSummary
    
    from .gravi_visual_class import graphoutdarkaxes

    from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image, PageBreak
    from reportlab.graphics.shapes import String
    from reportlab.lib.units import inch, cm, mm
    from reportlab.lib import colors
    import io

    from io import StringIO, BytesIO
    from svglib.svglib import svg2rlg

    #==============================================================================
    # Global parameters
    #==============================================================================

    datatype = dark.header['HIERARCH ESO PRO CATG']
    specres = dark.header['HIERARCH ESO INS SPEC RES']
    plotmargin = 0.15

    #==============================================================================
    # Start Story
    #==============================================================================
    
    Story = [Spacer(1,1*mm)]
    plotSummary (Story, filename, dark, onTarget=False)
    
    #==============================================================================
    # First page
    #==============================================================================
    
    if specres == 'HIGH':
        plotTitle(Story,"Median SC flux along X and Y (ADU/DIT)")

        resamp = 3
        hsize = 15*cm # horizontal size of plot
        vsize = 5*cm # vertical size of plot
        median_y_profile=np.zeros(dark.darkimage_sc.shape[1])
        pixvector = list(range(1,dark.darkimage_sc.shape[1]+1))
        # three lines are considered in the spectrum, the maximum is used to estimate the true intensity
        for y in range(0,dark.darkimage_sc.shape[1]):
            median_y_profile[y] = np.median(dark.darkimage_sc[:,y])
        yminval = np.percentile(median_y_profile,1)
        ymaxval = np.percentile(median_y_profile,99)
        yminval -= plotmargin*np.abs(ymaxval-yminval)
        ymaxval += plotmargin*np.abs(ymaxval-yminval)
        a = graphoutdarkaxes( pixvector[::resamp], median_y_profile[::resamp], 1, dark.darkimage_sc.shape[1], yminval, ymaxval, hsize,vsize,\
            'Median flux in direction of dispersion (median over outputs)')
        Story.append(a)
        
        if hasattr(dark, 'darkerror_sc'):
            hsize = 15*cm # horizontal size of plot
            vsize = 2.5*cm # vertical size of plot
            Story.append(Spacer(1,1*cm))
            median_y_profile=np.zeros(dark.darkerror_sc.shape[1])
            pixvector = list(range(1,dark.darkerror_sc.shape[1]+1))
            # three lines are considered in the spectrum, the maximum is used to estimate the true intensity
            for y in range(0,dark.darkimage_sc.shape[1]):
                median_y_profile[y] = np.nanmedian(dark.darkerror_sc[:,y])
            yminvalerr = np.percentile(median_y_profile,1)
            ymaxvalerr = np.percentile(median_y_profile,99)
            yminval -= plotmargin*np.abs(ymaxvalerr-yminvalerr)
            ymaxval += plotmargin*np.abs(ymaxvalerr-yminvalerr)
            a = graphoutdarkaxes( pixvector[::resamp], median_y_profile[::resamp], 1, dark.darkerror_sc.shape[1], yminvalerr, ymaxvalerr, hsize,vsize,\
            'RMS flux in direction of dispersion (median over outputs)')
            Story.append(a)
        
        Story.append(Spacer(1,7*mm))
    
        hsize = 15*cm # horizontal size of plot
        vsize = 5*cm # vertical size of plot
        median_x_profile=np.zeros(dark.darkimage_sc.shape[0])
        pixvector = list(range(1,dark.darkimage_sc.shape[0]+1))
        # One line is considered only, in between the spectra
        for x in range(0,dark.darkimage_sc.shape[0]):
            median_x_profile[x] = np.median(dark.darkimage_sc[x,:])
        yminval = np.percentile(median_x_profile,1)
        ymaxval = np.percentile(median_x_profile,99)
        yminval -= plotmargin*np.abs(ymaxval-yminval)
        ymaxval += plotmargin*np.abs(ymaxval-yminval)
        a = graphoutdarkaxes( pixvector[::resamp], median_x_profile[::resamp], 1, dark.darkimage_sc.shape[0], yminval, ymaxval, hsize,vsize,\
                'Median flux perpendicular to direction of dispersion (median over wavelengths)')
        Story.append(a)
        
        if hasattr(dark, 'darkerror_sc'):
            hsize = 15*cm # horizontal size of plot
            vsize = 2.5*cm # vertical size of plot
            Story.append(Spacer(1,1*cm))
            median_x_profile=np.zeros(dark.darkerror_sc.shape[0])
            pixvector = list(range(1,dark.darkerror_sc.shape[0]+1))
            for x in range(0,dark.darkerror_sc.shape[0]):
                median_x_profile[x] = np.median(dark.darkerror_sc[x,:])
            yminvalerr = np.percentile(median_x_profile,1)
            ymaxvalerr = np.percentile(median_x_profile,99)
            yminvalerr -= plotmargin*np.abs(ymaxvalerr-yminvalerr)
            ymaxvalerr += plotmargin*np.abs(ymaxvalerr-yminvalerr)
            a = graphoutdarkaxes( pixvector[::resamp], median_x_profile[::resamp], 1, dark.darkerror_sc.shape[0], yminvalerr, ymaxvalerr, hsize,vsize,\
                'RMS flux perpendicular to direction of dispersion (median over wavelengths)')
            Story.append(a)
            
    else: # For LOW and MEDIUM spectra only
        plotTitle(Story,"Median SC dark along direction of dispersion (ADU/DIT)")

        if specres == 'LOW':
            if dark.polarsplit == True:
                starty = 3
                stepy = 5
            if dark.polarsplit == False:
                starty = 3
                stepy = 5
        if specres == 'MEDIUM':
            if dark.polarsplit == True:
                starty = 4
                stepy = 7
            if dark.polarsplit == False:
                starty = 4
                stepy = 7
                
        yspec = np.arange(starty,stepy, dark.darkimage_sc.shape[0])
        ynospec = np.arange(starty - int(np.floor(stepy/2)), stepy, dark.darkimage_sc.shape[0])
        
        hsize = 15*cm # horizontal size of plot
        vsize = 5*cm # vertical size of plot
        median_y_profile=np.zeros(dark.darkimage_sc.shape[1])
        pixvector = list(range(1,dark.darkimage_sc.shape[1]+1))
        # three lines are considered in the spectrum, the maximum is used to estimate the true intensity
        for y in range(0,dark.darkimage_sc.shape[1]):
            median_y_profile[y] = np.nanmax([dark.darkimage_sc[yspec-1,y],dark.darkimage_sc[yspec,y],dark.darkimage_sc[yspec+1,y]])
        yminval = np.percentile(median_y_profile,1)
        ymaxval = np.percentile(median_y_profile,99)
        yminval -= plotmargin*np.abs(ymaxval-yminval)
        ymaxval += plotmargin*np.abs(ymaxval-yminval)
        a = graphoutdarkaxes( pixvector, median_y_profile, 1, dark.darkimage_sc.shape[1], yminval, ymaxval, hsize,vsize,\
            'Flux ON spectra (median of outputs)')
        Story.append(a)
        
        if hasattr(dark, 'darkerror_sc'):
            hsize = 15*cm # horizontal size of plot
            vsize = 2.5*cm # vertical size of plot
            Story.append(Spacer(1,1*cm))
            median_y_profile=np.zeros(dark.darkerror_sc.shape[1])
            pixvector = list(range(1,dark.darkerror_sc.shape[1]+1))
            # three lines are considered in the spectrum, the maximum is used to estimate the true intensity
            for y in range(0,dark.darkimage_sc.shape[1]):
                median_y_profile[y] = np.nanmax([dark.darkerror_sc[yspec,y],dark.darkerror_sc[yspec-1,y],dark.darkerror_sc[yspec-1,y]])
            yminvalerr = np.percentile(median_y_profile,0.5)
            ymaxvalerr = np.percentile(median_y_profile,99.5)
            yminval -= plotmargin*np.abs(ymaxvalerr-yminvalerr)
            ymaxval += plotmargin*np.abs(ymaxvalerr-yminvalerr)
            a = graphoutdarkaxes( pixvector, median_y_profile, 1, dark.darkerror_sc.shape[1], yminvalerr, ymaxvalerr, hsize,vsize,\
            'RMS ON spectra (median of outputs)')
            Story.append(a)
        
        Story.append(Spacer(1,7*mm))
    
        hsize = 15*cm # horizontal size of plot
        vsize = 5*cm # vertical size of plot
        median_y_profile=np.zeros(dark.darkimage_sc.shape[1])
        pixvector = list(range(1,dark.darkimage_sc.shape[1]+1))
        # One line is considered only, in between the spectra
        for y in range(0,dark.darkimage_sc.shape[1]):
            median_y_profile[y] = np.median(dark.darkimage_sc[ynospec,y])
        yminval = np.percentile(median_y_profile,1)
        ymaxval = np.percentile(median_y_profile,99)
        yminval -= plotmargin*np.abs(ymaxval-yminval)
        ymaxval += plotmargin*np.abs(ymaxval-yminval)
        a = graphoutdarkaxes( pixvector, median_y_profile, 1, dark.darkimage_sc.shape[1], yminval, ymaxval, hsize,vsize,\
                'Flux BETWEEN spectra (median of outputs)')
        Story.append(a)
        
        if hasattr(dark, 'darkerror_sc'):
            hsize = 15*cm # horizontal size of plot
            vsize = 2.5*cm # vertical size of plot
            Story.append(Spacer(1,1*cm))
            median_y_profile=np.zeros(dark.darkerror_sc.shape[1])
            pixvector = list(range(1,dark.darkerror_sc.shape[1]+1))
            for y in range(0,dark.darkerror_sc.shape[1]):
                median_y_profile[y] = np.median(dark.darkerror_sc[ynospec,y])
            yminvalerr = np.percentile(median_y_profile,0.5)
            ymaxvalerr = np.percentile(median_y_profile,99.5)
            yminvalerr -= plotmargin*np.abs(ymaxvalerr-yminvalerr)
            ymaxvalerr += plotmargin*np.abs(ymaxvalerr-yminvalerr)
            a = graphoutdarkaxes( pixvector, median_y_profile, 1, dark.darkerror_sc.shape[1], yminvalerr, ymaxvalerr, hsize,vsize,\
                'RMS BETWEEN spectra (median of outputs)')
            Story.append(a)
            
    Story.append(PageBreak())

    #==============================================================================
    # Summary of reduction parameters
    #==============================================================================

    plotReductionSummary(Story, dark)
    Story.append(PageBreak())
    
    #==============================================================================
    # Image display of the SC dark
    #==============================================================================
    
    if specres == 'LOW' or specres == 'MEDIUM':
        plotTitle(Story,"SC dark image (ADU/DIT), dispersion = horizontal")
    else:
        plotTitle(Story,"SC dark image (ADU/DIT), dispersion = vertical")
    
    plt.close('all')
    fig=plt.figure(figsize=(5,8))
    plt.rc('xtick', labelsize=5)
    plt.rc('ytick', labelsize=5)
    if specres == 'LOW' or specres == 'MEDIUM':
        figaspect = (1.0*dark.darkimage_sc.shape[1]/dark.darkimage_sc.shape[0])*2.0
        plt.imshow(dark.darkimage_sc,vmin=np.percentile(dark.darkimage_sc,1),vmax=np.percentile(dark.darkimage_sc,99),\
            cmap='cubehelix', interpolation='nearest', aspect=figaspect)
    else: # HIGH resolution, the spectrum is rotated by 90 deg
        figaspect = (1.0*dark.darkimage_sc.shape[0]/dark.darkimage_sc.shape[1])*2.0
        plt.imshow(dark.darkimage_sc.T,vmin=np.percentile(dark.darkimage_sc,1),vmax=np.percentile(dark.darkimage_sc,99),\
            cmap='cubehelix', interpolation='nearest', aspect=figaspect)
    plt.colorbar()

    imgdata = BytesIO()
    fig.savefig(imgdata, format='svg', bbox_inches='tight')
    imgdata.seek(0)  # rewind the data
    drawing = svg2rlg(imgdata)
    Story.append(drawing)

    Story.append(PageBreak())

    #==============================================================================
    # Image display of the SC dark std
    #==============================================================================
    
    plotTitle(Story,"SC dark standard deviation (ADU/DIT)")
    
    plt.close('all')
    fig=plt.figure(figsize=(6,8))
    plt.rc('xtick', labelsize=5)
    plt.rc('ytick', labelsize=5)
    if specres == 'LOW' or specres == 'MEDIUM':
        figaspect = (1.0*dark.darkerror_sc.shape[1]/dark.darkerror_sc.shape[0])*2.0
        plt.imshow(dark.darkerror_sc,vmin=np.percentile(dark.darkerror_sc,1),vmax=np.percentile(dark.darkerror_sc,97),\
            cmap='cubehelix', interpolation='nearest', aspect=figaspect)
    else: # HIGH resolution, the spectrum is rotated by 90 deg
        figaspect = (1.0*dark.darkerror_sc.shape[0]/dark.darkerror_sc.shape[1])*2.0
        plt.imshow(dark.darkerror_sc.T,vmin=np.percentile(dark.darkerror_sc,1),vmax=np.percentile(dark.darkerror_sc,97),\
            cmap='cubehelix', interpolation='nearest', aspect=figaspect)
    plt.colorbar()

    imgdata = BytesIO()
    fig.savefig(imgdata, format='svg', bbox_inches='tight')
    imgdata.seek(0)  # rewind the data
    drawing = svg2rlg(imgdata)
    Story.append(drawing)

    Story.append(PageBreak())

    #==============================================================================
    # Median FT dark profiles
    #==============================================================================

    plotTitle(Story,"Median FT dark transverse profiles (ADU/DIT)")

    hsize = 15*cm # horizontal size of plot
    vsize = 6*cm # vertical size of plot
    median_y_profileft=np.zeros(dark.darktable_ft.shape[1])
    pixvector = list(range(1,dark.darktable_ft.shape[1]+1))
    for y in range(0,dark.darktable_ft.shape[1]):
        median_y_profileft[y] = np.median(dark.darktable_ft[:,y])
    yminvalft = np.percentile(median_y_profileft,0.5)
    ymaxvalft = np.percentile(median_y_profileft,99.5)
    yminvalft -= plotmargin*np.abs(ymaxvalft-yminvalft)
    ymaxvalft += plotmargin*np.abs(ymaxvalft-yminvalft)
    a = graphoutdarkaxes( pixvector, median_y_profileft, 1, dark.darktable_ft.shape[1], yminvalft, ymaxvalft, hsize,vsize, 'Median along columns (direction of dispersion)')
    
    Story.append(a)
    Story.append(Spacer(1,1*cm))
    
    median_y_profilefterr=np.zeros(dark.darkerror_ft.shape[1])
    pixvector = list(range(1,dark.darkerror_ft.shape[1]+1))
    for y in range(0,dark.darkerror_ft.shape[1]):
        median_y_profilefterr[y] = np.median(dark.darkerror_ft[:,y])
    yminvalerrft = np.percentile(median_y_profilefterr,0.5)
    ymaxvalerrft = np.percentile(median_y_profilefterr,99.5)
    yminvalerrft -= plotmargin*np.abs(ymaxvalerrft-yminvalerrft)
    ymaxvalerrft += plotmargin*np.abs(ymaxvalerrft-yminvalerrft)
    a = graphoutdarkaxes( pixvector, median_y_profilefterr, 1, dark.darkerror_ft.shape[1], yminvalerrft, ymaxvalerrft, hsize,vsize, 'Median RMS along columns (direction of dispersion)')
    
    Story.append(a)    
    Story.append(Spacer(1,1*cm))
    
    median_x_profileft=np.zeros(dark.darktable_ft.shape[0])
    pixvector = list(range(1,dark.darktable_ft.shape[0]+1))
    for x in range(0,dark.darktable_ft.shape[0]):
        median_x_profileft[x] = np.median(dark.darktable_ft[x,:])
    xminvalft = np.percentile(median_x_profileft,0.5)
    xmaxvalft = np.percentile(median_x_profileft,99.5)
    a = graphoutdarkaxes( pixvector, median_x_profileft, 1, dark.darktable_ft.shape[0], xminvalft, xmaxvalft, hsize,vsize, 'Median along lines (perpendicular to direction of dispersion)')
    
    Story.append(a)
    Story.append(PageBreak())

    #==============================================================================
    # FT dark image
    #==============================================================================

    plotTitle(Story,"FT dark image (ADU/DIT), dispersion = horizontal")
       
    plt.close('all')
    fig=plt.figure(figsize=(6,8))
    plt.rc('xtick', labelsize=5)
    plt.rc('ytick', labelsize=5)
    valmin = np.min([xminvalft,yminvalft])
    valmax = np.max([xmaxvalft,ymaxvalft])
    figaspect = (1.0*dark.darktable_ft.shape[1]/dark.darktable_ft.shape[0])*2.0
    plt.imshow(dark.darktable_ft,vmin=valmin,vmax=valmax,cmap='cubehelix', interpolation='nearest', aspect=figaspect)
    plt.colorbar()

    imgdata = BytesIO()
    fig.savefig(imgdata, format='svg', bbox_inches='tight')
    imgdata.seek(0)  # rewind the data
    drawing = svg2rlg(imgdata)
    Story.append(drawing)

    Story.append(PageBreak())    

    #==============================================================================
    # FT dark std image
    #==============================================================================

    plotTitle(Story,"FT dark image standard deviation (ADU/DIT)")
    
    plt.close('all')
    fig=plt.figure(figsize=(6,8))
    plt.rc('xtick', labelsize=5)
    plt.rc('ytick', labelsize=5)
    valmin = np.percentile(dark.darkerror_ft,0.5)
    valmax = np.percentile(dark.darkerror_ft,99.5)
    valmin -= plotmargin*np.abs(valmax-valmin)
    valmax += plotmargin*np.abs(valmax-valmin)
    figaspect = (1.0*dark.darkerror_ft.shape[1]/dark.darkerror_ft.shape[0])*2.0
    plt.imshow(dark.darkerror_ft,vmin=valmin,vmax=valmax,cmap='cubehelix', interpolation='nearest', aspect=figaspect)
    plt.colorbar()

    imgdata = BytesIO()
    fig.savefig(imgdata, format='svg', bbox_inches='tight')
    imgdata.seek(0)  # rewind the data
    drawing = svg2rlg(imgdata)
    Story.append(drawing)

    plt.close('all')

    #==============================================================================
    # Create PDF report from Story
    #==============================================================================
    print("Create the PDF")
    
    gravi_visual_class.TITLE    = "GRAVITY "+datatype+" Quality Control Report"
    gravi_visual_class.PAGEINFO = datatype+" file: "+filename+".fits"
    reportname = filename+"-"+datatype+".pdf"
    
    doc = SimpleDocTemplate(reportname)
    doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)

    print((" "+reportname)) 

##==============================================================================
## MAIN PROGRAM    
##==============================================================================

if __name__ == '__main__':
    import sys
    if len(sys.argv) == 2 :
        filename=sys.argv[1]
    
    if filename == '' :
        filename=input(" Enter DARK file name (without .fits) : ")
    
    #filename = "/Users/kervella/Pipelines/GRAVITY.2016-03-26T02-29-26_sky"
    #filename = "/Users/kervella/Pipelines/GRAVITY.2016-03-18T04-58-51_dark"
    #filename = "/Users/kervella/Pipelines/GRAVITY.2016-03-18T05-53-58_dark"

    dark = gravi_visual_class.Dark(filename+'.fits')

    produce_dark_report(dark,filename)
