#!/usr/bin/env python
import os, sys, glob, subprocess, shutil
import re, string
import numpy as np
from datetime import datetime

__authors__ = ["Ming Chen"]
__license__ = "Public Domain"
__maintainer__ = "Ming Chen"
__email__ = "ming.chen@noaa.gov"
__date__  = "Mar 24, 2023"

'''
#####################################################################
# 
# ucar2umd_att.py
#
# Purpose:
# This Python library provides utilities to combine UCAR sub-daily LEO
# attitude data files into daily or hourly input datasets for the
# BERNESE software package.
##
# History:  
#       Created by: Ming Chen 2023/03/24
#                   ming.chen@noaa.gov
# 
# Usage: from ucar2umd_att importU CAR2UMD_ATT
#
#
#####################################################################

'''
 
class UCAR2UMD_ATT(object):

   def __init__(self, mission='cosmic2'):
      self.mission=mission
      self.clean()

   def __del__(self):
      del self.header
      del self.dataset

   def clean(self):
      self.header = []
      self.dataset = {}
      self.add_header = True
      self.start_time = '+first____ zzzz'
      self.end_time = '+last____ 0000' 


   def write_rinex(self, outfile='Test.out', **kwargs):
       verbose = kwargs.get('verbose', False)
       psatellite = r'(\s*\+satellite\s+\d+\s+)(\w+)(\s*$)'
       satellite = kwargs.get('satellite', psatellite)
       for i in range(len(self.header)):
          if self.header[i].find("first") != -1: 
             self.header[i] = self.start_time
          elif self.header[i].find("last") != -1: 
             self.header[i] = self.end_time
          elif re.match(psatellite, self.header[i]): 
             sat = re.search(psatellite, self.header[i])
             satellite = kwargs.get('satellite', sat[2])
             self.header[i] = sat[1] + satellite + sat[3]
             #self.header[i] = sat[1] + self.mission.upper() + sat[3]
 
       ds = self.dataset
       mykeys = list(ds.keys())
       mykeys.sort()
       self.dataset = {i: ds[i] for i in mykeys}

       if verbose: print("output: {}".format(outfile))
       with open(outfile,'w') as f:
          for line in self.header:
             f.write(line)

          for k,v in self.dataset.items():
             #print(k,  v[0], len(v)
             for line in v:
                f.write(line)
       
   def add_rinex(self, filename, **kwargs):      
       verbose = kwargs.get('verbose', False)
       # ftype = os.path.splitext(filename)[1]
       if not os.path.isfile(filename):
         err = "Error: file not exis {} ... ".format(filename)
         print(err)
         return(False)
       if(verbose): print(filename)
       
       btime = r'(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\.\d+)'
       htime = r'(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\.\d+)\s+(\w+)\s+(\.+)'
       pdata = r'(att|sca|ang|pve|pvi|tor|sad)'

       pheader = r'[\%\+\*]'
       peh=re.compile(r'^\s*'+pheader)
       pbt=re.compile(r'^\s*tim\s*'+btime)
       pdd=re.compile(r'^\s*'+pdata)
       pdlist = ['tim','att','sca','ang','pve', 'pvi','tor','sad' ]
       
       fp = open(filename, 'r' )
       nnn = 0 ; headerlines = 0; N = 0
       line = fp.readline() ; nnn += 1
       while True :
           if len(line) == 0: break
           #line=line.replace("\n", "")
           if (headerlines == 0):
              while peh.match(line) != None:
                  headerlines += 1            
                  if self.add_header: self.header.append(line)
                  if line.find("first") != -1:
                     if(verbose): print(line)
                     if line.strip() < self.start_time.strip(): self.start_time = line
                  if line.find("last") != -1:
                     if(verbose): print(line)
                     if line.strip() > self.end_time.strip(): self.end_time = line
                  line = fp.readline() ; nnn += 1
              if self.add_header:
                 self.add_header = False
          
           if pbt.match(line):
              ts = pbt.search(line)
              dstr1="{:02d}{:02d}{:02d}".format(int(ts[1]),int(ts[2]),int(ts[3]))
              dstr2="T{:02d}:{:02d}:{:06.3f}".format(int(ts[4]),int(ts[5]),float(ts[6]))
              dkey=dstr1+dstr2
              sec    = float(ts[6])
              current_time = datetime(
                int(ts[1]), int(ts[2]), int(ts[3]), int(ts[4]), int(ts[5]),
                int(sec),
                int((sec % 1) * 1e6)
               )
              
              datalines = [line] ; n = 1  
              line = fp.readline() ; nnn += 1
              while not pbt.match(line):
                  if len(line) == 0: break
                  if len(line.strip()) == 0:
                     continue
                  if (pdd.match(line) != None):
                     datalines.append(line) ; n = n + 1
                  line = fp.readline() ; nnn += 1
              if N == 0: N = n
              if N == n:  
                 self.dataset[dkey] = datalines
              else:
                 if(verbose): print('Inconsistent record error ... {} != {} \n'.format(n,N))
 
       fp.close()
       return 


   def extract_rinex(self, filein, outfile='Test.out', **kwargs):
       verbose = kwargs.get('verbose', False)
       psatellite = r'(\s*\+satellite\s+\d+\s+)(\w+)(\s*$)'
       btime = r'(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\.\d+)'
       pdata = r'(att|sca|ang|pve|pvi|tor|sad)'
       pdata = r'(pve)(.+)'
       pheader = r'[\%\+\*]'
       peh=re.compile(r'^\s*'+pheader)
       pbt=re.compile(r'^\s*tim\s*'+btime)
       pdd=re.compile(r'^\s*'+pdata)
 
       for i in range(len(self.header)):
          if self.header[i].find("first") != -1: 
             print("first: ", self.start_time)
          elif self.header[i].find("last") != -1: 
             print("last: ", self.end_time)
 
       ds = self.dataset
       mykeys = list(ds.keys())
       mykeys.sort()
       self.dataset = {i: ds[i] for i in mykeys}
   
       if verbose: print("output: {}".format(outfile))
       with open(outfile,'w') as f:
          for k,v in self.dataset.items():
             #print(k,  v[0], len(v))
             newline=''
             d = datetime.strptime(k,'%Y%m%dT%H:%M:%S.%f')
             #dstr = d.strftime("%Y/%m/%d %H:%M:%S.%f")[:-3]
             dstr = d.strftime("%Y/%m/%d %H:%M:%S.%f")

             for line in v:
                if (pdd.match(line) != None):
                    ds = pdd.search(line)
                    newline =  newline + ds[2] +"\n"
             f.write(dstr+ " " + newline)

if __name__ == "__main__":
   import argparse

   parser = argparse.ArgumentParser(description='Main program')
   parser.add_argument("input", type=str,  help="leo attitude rinex input file")
   parser.add_argument("output", type=str,  help="extracted pre output ")

   args = parser.parse_args()
   filein= args.input ; fileout= args.output
   umd = UCAR2UMD_ATT()
   umd.add_rinex(filein, verbose=True)
   umd.extract_rinex(filein, outfile=fileout, verbose = True )  
