#!/usr/bin/env python


import os
import sys
import stat
import tempfile
import pickle
import xml.etree.ElementTree as ET
from datetime import datetime


# Load location specific info
from chart_config_v2 import *

__version__ = "08 March 2024"
ListOfMultiObiObsIds = ["82","108","279","380","400","433","800","861","897","906","943","1411","1431","1456","1561","1578","2010","2042","2077","2365","2783","3057","3182","3764","4175","60879","60880","62249","62264","62796"]  # KJG created 4/15/2015 -- list is expected to always be static


# ciao stuff
from pycrates import read_file
from coords.format import *


from chart_classes import *


def email_user( addr, files, ftpserver, asol ):
    """
    Email user for pick up
    """
    # ~ from email.mime.text import MIMEText
    # ~ from smtplib import SMTP

    files.sort()
    
    ff = "\n    ".join( [ "{1}/{0}\t{2} bytes".format(s,ftpserver,r) for s,r in files ] )

    txt = """Content-type: text/plain

   
    Your ChaRT simulations are available for retrieval

    {}

    The ChaRT threads explain how to analyze ray files.    

        https://cxc.cfa.harvard.edu/ciao/PSFs/chart2/index.html
    
    """.format(ff)


    if asol.infile != "none":
        txt += """
        Be sure to use the same aspect solution file with MARX or psf_project_ray
        
        pset marx DitherModel=FILE DitherFile={asp}
          or
        pset psf_project_ray asolfile={asp}
        """.format(asp=asol.infile)

    print(txt)

    # ~ msg = MIMEText( txt )
    # ~ msg["Subject"] = "ChaRT rays ready for download"
    # ~ msg["From"] = RAYRUNNER
    # ~ msg["To"] = addr
    # ~ msg["Bcc"] = "kglotfelty@cfa.harvard.edu"
            
    # ~ try:
        # ~ s=SMTP("head.cfa.harvard.edu")
        # ~ s.sendmail( RAYRUNNER, [msg["To"]]+[msg["Bcc"]], msg.as_string())
        # ~ s.quit()
    # ~ except Exception as ee:
        # ~ ###sys.stdout.write(str( ee)+"\n")
        # ~ ###sys.stdout.write("Error sending email\n")
        # ~ pass
 

def simulate( asol, spectrum, coords, evtfile, loop, randseed ):
    """
    Runs run_saotrace_and_marx using the inputs
    """


    def set_randseed( val ):
        from datetime import datetime
        rs = int(val)
        if rs <= 0:  # saotrace doesn't like 0 either
            rs = datetime.now().microsecond
        return rs
        
    def _make_tool():
        from ciao_contrib.runtool import ParValue, ParSet,ParRange,CIAOToolParFile
        req =  [ParValue("infile","f","Event or Image file",None),ParValue("outroot","f","Output root name",None),ParRange("ra","r","Right Asscension of source [deg]",0,0,360),ParRange("dec","r","Declination of source [deg]",0,-90,90),ParValue("spectrumfile","f","ASCII 3 column spectrum file [photon/cm^2/sec]",None)]
        opt = [ParRange("monoenergy","r","Monochromatic energy [keV]",None,0,10),ParValue("flux","r","Flux value for spectrum or monochromatic energy",None),ParSet("simulator","s","Which tool to simulate HRMA?",'saotrace',["saotrace","marx","file"]),ParValue("rayfile","f","Use existing rays file",None),ParSet("projector","s","Which tool to project",'marx',["marx","psf_project_ray","none"]),ParRange("random_seed","i","SAO-SAC PSF random seed",1,0,1073741824),ParRange("blur","r","Blur (marx.AspectBlur or psf_project_ray.xblur) [arcsec]",0.07,0,None),ParValue("readout_streak","b","MARX Simulate readout streak (ACIS)",False),ParValue("pileup","b","MARX Run pileup module (ACIS)",False),ParValue("ideal","b","Should MARX use idealized detectors (QE=1) be used?",True),ParValue("extended","b","Should MARX detectors be extended beyond their physical edges?",True),ParRange("binsize","r","Image bin size [pix]",1,0,None),ParRange("numsig","r","Number of sigma to make image",7,1,None),ParValue("minsize","i","Minimum image size [pix]",None),ParRange("numiter","i","Number of simulations to average together",1,1,None),ParRange("numrays","i","Number of rays to simulate",None,0,None),ParValue("keepiter","b","Keep files from each iteration?",False),ParValue("asolfile","f","Aspect solution file: blank=autofind, none=omit",None),ParValue("saotrace_install","f","Directory where SAOTrace was intalled",'${INSTALLDIR}'),ParValue("saotrace_db","f","Direcotry where SAOTrace database was intalled",'${SAOTRACE_DB}'),ParValue("saotrace_mirror","s","SAOTrace mirror configuration",'orbit-200809-01f-a'),ParValue("marx_root","f","Directory where MARX is installed",'${MARX_ROOT}'),ParRange("verbose","i","Chatter level of tool",1,0,5)]
        rsam = CIAOToolParFile("simulate_psf", req, opt )
        return rsam

    def make_outroot():
        ra,dec,roll = asol.get_ra_dec_roll()
        if spectrum.infile:
            energy=spectrum.infile
        else:
            energy="en{}_flux{}".format( spectrum.mono, spectrum.flux)
        
        if asol.infile != "none":
            asp="dithered"
        else:
            asp="pointed"

        outroot = "HRMA_ra{ra:.5f}_dec{dec:.5f}_{energy}_{asol}".format(ra=float(coords[0]),dec=float(coords[1]),energy=energy,asol=asp)
        return outroot


    from ciao_contrib.runtool import make_tool
    #rsam = make_tool("simulate_psf")
    rsam = _make_tool()
    rsam.infile = evtfile
    rsam.outroot=make_outroot()
    
    rsam.asolfile = asol.infile
    rsam.ra = coords[0]
    rsam.dec = coords[1]


    spectrum.set_params( rsam ) # spectrum knows which parameters to set.
    loop.set_params(rsam)

    rsam.simulator="saotrace"
    rsam.projector="none"  # special token to just run rays
    
    rsam.keep = True
    rsam.marx_root="none"

    rsam.random_seed = set_randseed(randseed)
    rsam.verbose=1
    #print(rsam)
    rsam()

    outfile = [x for x in os.listdir(".") if x.startswith("HRMA")]
    return outfile


def copy_to_ftp( outfiles, ftpdir ):
    """
    Copy files to the FTP server, make sure world readable
    """
    from shutil import copy
    from tarfile import open

    root = outfiles[0].split("_i00")[0]
    outfile = root+".tar.gz"
    tar = open( outfile, "w|gz")
    for ff in outfiles:
        tar.add(ff)
    tar.close()

    os.makedirs(ftpdir, exist_ok=True)
    read_only = stat.S_IROTH | stat.S_IRGRP | stat.S_IRUSR | stat.S_IWUSR
    copy( outfile, ftpdir )
    os.chmod( os.path.join(ftpdir, outfile), read_only )

    return [( outfile, os.path.getsize(outfile) )]



def main():

    tmpdir = sys.argv[1]

    try:
        tmpdir = TmpDir( tmpdir ) # make sure it gets deleted
        os.chdir(tmpdir)
        with open("pickle.obj", "rb") as fp:
            (asol,spectrum,evtfile,coords,email,loop,randseed) = pickle.load(fp)

        # Do the real work
        outfiles = simulate( asol, spectrum, coords, evtfile, loop, randseed )
        retvals = copy_to_ftp( outfiles, FTP_ROOT)
        email_user( email, retvals, FTP_SERVER, asol)

    except Exception as ee:
        import traceback as traceback

        exc_type, exc_value, exc_traceback = sys.exc_info()

        err = str(ee)
        err = err+"\n"+str(traceback.format_tb(exc_traceback))

        err = "Content-type: text/plain\n\n"+err
        print(err)

        #~ from email.mime.text import MIMEText
        #~ from smtplib import SMTP

        #~ msg = MIMEText( err )
        #~ msg["Subject"] = "Error running ChaRT"
        #~ msg["From"] = RAYRUNNER
        #~ msg["To"] = email
        #~ msg["Bcc"] = "kglotfelty@cfa.harvard.edu"
        #~ s=SMTP("head.cfa.harvard.edu")
        #~ s.sendmail( RAYRUNNER, [msg["To"]]+[msg["Bcc"]], msg.as_string())
        #~ s.quit()
        raise

    # fin!


if __name__ == "__main__":

    try:
        main()
    except Exception as E:
        sys.stdout.write("\nERROR: "+str(E)+"\n")
        sys.exit(1)
    sys.exit(0)




