########################################################################3
#  task_importgmrt.py
#
#
# Copyright (C) 2009
# Associated Universities, Inc. Washington DC, USA.
#
# This script is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
#
# Correspondence concerning AIPS++ should be adressed as follows:
#        Internet email: aips2-request@nrao.edu.
#        Postal address: AIPS++ Project Office
#                        National Radio Astronomy Observatory
#                        520 Edgemont Road
#                        Charlottesville, VA 22903-2475 USA
#
# <author>
# Shannon Jaeger (University of Calgary)
# </author>
#
# <summary>
# </summary>
#
# <reviewed reviwer="" date="" tests="" demos="">
# </reviewed
#
# <etymology>
# importgmrt stands for import GMRT UV FITS data.
# </etymology>
#
# <synopsis>
# task_importgmrt.py is a Python script providing an easy to use task
# for importing GMRT FITS data files into the CASA system.  A measurement
# set is produced from the GMRT FITS file.
#
# The given flag files are read and data is flagged according to
# the information found in these files. It is expected that the
# FLAG files are in the old AIPS TVFLAG file format.
#
# </synopsis> 
#
# <example>
# <srcblock>

# </srblock>
# </example>
#
# <motivation>
# To provide a user-friendly method for importing GMRT FITS files.
# </motivation>
#
# <todo>
# </todo>

from __future__ import absolute_import

import os
import numpy

# get is_CASA6 and is_python3
from casatasks.private.casa_transition import *
if is_CASA6:
    from casatools import table, ms, agentflagger, quanta
    from casatasks import casalog, importuvfits
    from .mstools import write_history

    _qa = quanta( )
else:
    from importuvfits import *
    from taskinit import *
    from mstools import write_history
    #from fg import *

    # not a local tool
    _qa = qa

def importgmrt( fitsfile, flagfile, vis ):

    # First check if the output file exists. If it
    # does then we abort.  CASA policy prevents files
    # from being over-written.
    #
    # Also if the vis name given is the empty string
    # we use the default name, input fitsfile with
    # "fits" removed
    if ( len( vis ) < 1 ):
        vis = ''
        fits_list=fitsfile.split( '.' )
        last = len(fits_list)
        if ( fits_list[last-1].lower() == 'fits' or \
             fits_list[last-1].lower() == 'fit' ):
            last = last -1
        for i in range( last ):
            if ( len ( vis ) < 1 ):
                vis = fits_list[i]
            else:
                vis = vis + '.'+fits_list[i]
        vis=vis+'.MS'
        
        casalog.post( "The vis paramter is empty, consequently the" \
                      +" the default visibilty file\nname will be used, "\
                      + vis, 'WARN' )
    if ( len( vis ) > 0 and os.path.exists( vis ) ):
        raise RuntimeError( 'Visibility file, '+vis+\
                            ' exists. import GMRT can not proceed, please\n'+\
                            'remove it or set vis to a different value.')

    # Loop through the list of flag files and make sure each one
    # of them exists
    if isinstance( flagfile, str ):
        if ( len( flagfile ) > 0 ):
            flagfile=[flagfile]
        else:
            flagfile=[]
    
    for i in range( len( flagfile ) ):
        if ( not os.path.exists( flagfile[i] ) ):
            msg = 'Unable to locate FLAG file '+ flagfile[i]
            raise RuntimeError(msg)
        

    # Ok, we've done our preliminary checks, now let's get
    # down to business and import our fitsfile.
    casalog.post( 'Starting import ...', 'NORMAL' )
    importuvfits( fitsfile, vis )

    if is_CASA6:
        mytb = table( )
        myms = ms( )
        aflocal = agentflagger( )
    else:
        mytb, myms = gentools(['tb', 'ms'])
        aflocal = casac.agentflagger()

    # Write history
    try:
        param_names = importgmrt.__code__.co_varnames[:importgmrt.__code__.co_argcount]
        if is_python3:
            vars = locals( )
            param_vals = [vars[p] for p in param_names]
        else:
            param_vals = [eval(p) for p in param_names]
        ok &= write_history(myms, vis, 'importgmrt', param_names,
                            param_vals, casalog)
    except Exception as instance:
        casalog.post("*** Error \'%s\' updating HISTORY" % (instance), 'WARN')
    
    # CASA's importuvfits doesn't understand the GMRT antenna
    # names very well and/or the FITS files tend to put the
    # antenna names in a place that CASA doesn't look for them.
    # Luckily the information seems to be in the "station"
    # information.  So let's fix up the Name column.
    casalog.post( 'Correcting GMRT Antenna names.', 'NORMAL1' )
    try:
        mytb.open( vis+'/ANTENNA', nomodify=False )
        stations = mytb.getcol('STATION')
        names    = []
        for idx in range( 0, len( stations ) ):
            names.append( stations[idx].split(':')[0] )
        mytb.putcol( 'NAME', numpy.array( names ) )
        mytb.done()
    except Exception as instance:
        casalog.post( 'Unable to properly name the antennas, but continuing')
        casalog.post( str(instance), 'WARN' )

    # If we don't have a flagfile then we are done!
    # Yippee awe eh!
    if ( len( flagfile ) < 1 ):
        return

    # We've imported let's find out the observation start
    # and end times, this will be needed for flagging.
    # We use it to find the different days the observation
    # was done on.
    startObs = ''
    endObs   = ''
    try: 
        myms.open( vis )
        trange=myms.range( 'time' )['time']
        myms.done()

        # Now have the observation time range in a numpy array.
        startObs = _qa.time( str( trange[0] )+'s', prec=8, form='ymd' )[0]
        endObs   = _qa.time( str( trange[1] )+'s', prec=8, form='ymd' )[0]
        
    except Exception as instance:
        msg =  'Unable to find obaservation start/en times: {}'.format(instance)
        raise RuntimeError(msg)
    
    days=[]
    startYY = startObs.split('/')[0]
    startMM = startObs.split('/')[1]
    startDD = startObs.split('/')[2]

    endYY = endObs.split('/')[0]
    endMM =endObs.split('/')[1]
    endDD =endObs.split('/')[2]    

    for year in range( int( startYY ), int( endYY ) + 1 ):
        for month in range( int( startMM ), int( endMM ) + 1 ):
            for day in range( int( startDD ), int( endDD ) + 1 ):
                days.append( str(year) + '/' + str(month) + '/' + str(day) + '/' )
        casalog.post( "DAYS: "+str(days), 'DEBUG1')


    # Read through the flag file(s) and assemble it into
    # a data structure.  The hope is to minimize the
    # number of calls to "flagdata" to make the flagging
    # fast!
    #
    # The expected file format is what is the flag file
    # format used by TVFLAG/UVFLAG in AIPS, which is as follows:
    #    1. If a line starts with '!' it's a comment
    #    2. 
    #
    casalog.post( 'Starting the flagging ...', 'NORMAL' )
                                          
    # First lets save the flag information as we got it from the
    # flag file.
    aflocal.open( vis )
    aflocal.saveflagversion( 'none', 'No flagging performed yet' )
    aflocal.done()

    for file in flagfile:
        casalog.post( 'Reading flag file '+file, 'NORMAL2' )
        FLAG_FILE = open( file, 'r' )
        line = FLAG_FILE.readline()
        ant_names = []          
        
        while ( len( line ) > 0 ):
            casalog.post( 'Read from flag file: '+str(line), 'DEBUG1' )

            # Default antenna list and time range
            antennas  = []
            baselines = []
            timerange = []

            # Skip comment lines, and the end of file.
            if ( len(line) < 1 or ( line[0] == '!' and line[2:6] !=  'PANT' ) ):
                                line = FLAG_FILE.readline()
                                continue
                        
            # Store the antenna name list
            if ( line[0:6] == '! PANT' ):                       
                ant_names= line.split(':')[1].lstrip(' ').split(' ')
                line = FLAG_FILE.readline()
                continue

            # First divide lines up on spaces
            casalog.post( 'LINE READ: '+line, 'DEBUG1' )
            step1=line.split(' ')   
            if ( len( step1 ) < 2 ):
                # We want a line with something on it.
                line = FLAG_FILE.readline()
                continue

            # Parse each bit of the string looking for the
            # antenna and timrange information.
            for i in range( len( step1 ) ):
                step2=step1[i].split('=')
                
                if ( len( step2 ) != 2 ):
                    # We want something with an equals sign in it!
                    continue
                casalog.post( 'keyword/value: '+str(step2), 'DEBUG1' )


                if ( step2[0].upper().startswith( 'ANT' ) ):
                    # Should be a comma separated list which
                    # is acceptable to flag data
                    #antennas=list(step2[1].split(',')
                    antennas=step2[1]
                    casalog.post( "antennas: "+antennas, 'DEBUG1')


                if ( step2[0].upper().startswith( 'BASEL' ) ):
                    # Should be a comma separated list which
                    # is acceptable to flag data
                    baselines=step2[1]
                    casalog.post( "baselines: "+baselines, 'DEBUG1')

                if ( step2[0].upper() == 'TIMERANGE' ):
                    # Time in the FLAG file is in the format
                    #   start-day,start-hour,start-min,star-sec,\
                    #   end-day,end-hour,end-min,end-sec
                    #
                    # CASA expects data to be of the form
                    #   YYYY/MM/DD/HH:MM:SS~YYYY/MM/DD/HH:MM:SS
                    # http://casa.nrao.edu/Memos/msselection/node8.html
                    #
                    # We use the day # to index into our days list and
                    # append the time on the end.  But day # starts at
                    # 1 and indexing starts at 0 so we need to adjust.
                    times     = step2[1].split(',')
                    casalog.post( "time: "+str(times), 'DEBUG1')
                    if ( int(times[0]) < 1 and int(times[4]) > len(days) ):
                        # All data for this antenna
                        timerange = ''
                    elif ( int(times[0]) < 1 ):
                        # We want all time before the end time
                        timerange = '<' + days[int(times[4])-1] \
                                    + times[5] + ':' + times[6] + ':' +times[7]
                    elif ( int(times[4]) > len(days) ):
                        # We want all times after the start time
                        timerange = '>' + days[int(times[0])-1] \
                                    + times[1]+':'+times[2]+':'+times[3]
                    else:
                        # We ahve a fully specified time range
                        timerange = days[int(times[0])-1] \
                                + times[1]+':'+times[2]+':'+times[3]\
                                +'~'\
                                +days[int(times[4])-1] \
                                +times[5]+':'+times[6]+':'+times[7]
                
            # Construct the antenna query string
            #
            # Verify the syntax of the ANTENNA & BASELINE keywords, 
            # if ANTENNA will always have only one.  I suspect we
            # with to loop through the baselines only here.
                        #
                        # OLD CODE FOR creating ANT SELECTION STRING
                        #
            #antStr=''
            #selectAntStr=''
            #if ( len( antennas ) > 0 and len( baselines ) > 0 ):
            #    # We are selecting baselines.
            #    for ant1 in antennas:
            #        for ant2 in baselines:
            #            if ( len( antStr ) < 1 ):
            #                antStr=str(int(ant1)-1)+'&'+str(int(ant2)-1)
            #    selectAntStr=antStr
            #elif ( len( antennas ) > 0 ):
            #    antStr=str(int(antennas)-1)
            #    # A hack to make sure we always have some unflagged data.
            #    # CASA seg faults if the myfg.setdata() results in no data.
            #    selectAntStr+=antStr+','+antennas

            
            antStr=''
            #if ( len( antennas ) > 0 and len( baselines ) > 0 ):
                        #       # We are selecting baselines.
                        #       for ant1 in antennas:
            #        for ant2 in baselines:
            #            if ( len( antStr ) < 1 ):
            #                antStr=str(int(ant1)-1)+'&'+str(int(ant2)-1)
                        #    selectAntStr=antStr
            #elif ( len( antennas ) > 0 ):
            if ( len( antennas ) > 0 ):
                antStr = ant_names[ int(antennas)-1 ].strip( ' ' )

            try:
#                casalog.post( "flagdata( "+vis+", mode='manualflag', antenna='"
#                              +antStr+"', timerange='"+timerange+"' )", 'NORMAL')
                casalog.post( "flagdata( "+vis+", mode='manual', antenna='"
                              +antStr+"', timerange='"+timerange+"' )", 'NORMAL')
                #flagdata( vis, mode='manual', selectdata=True, \
                #            antenna=antStr, timerange=timerange, \
                #            flagbackup=False )
                aflocal.open(vis)
                aflocal.selectdata(timerange=timerange)
                aflocal.parsemanualparameters(antenna=antStr, timerange=timerange)
                aflocal.init()
                aflocal.run(True, True)
                aflocal.done()
            except Exception as instance:
                msg = 'Unable to flag data from flag file '+file\
                      +'.\nAntennas='+antennas+' and timerange='\
                                     +timerange
                raise RuntimeError(msg)

            line = FLAG_FILE.readline()
            
        FLAG_FILE.close()

    # Save a Flag version so we can revert back to it if we wish
    aflocal.open( vis )
    aflocal.saveflagversion( 'import', 'Flagged the data from the GMRT flag file' )
    aflocal.done()