#!/usr/bin/env python
import os, sys, glob
import subprocess
from datetime import datetime, timedelta
from gpsdate import mkdate, fmtdate, date2gpsw
#from gpsdate import mkdate, fmtdate, date2gpsw


__authors__ = ["Ming Chen"]
__license__ = "Public Domain"
__maintainer__ = "Ming Chen"
__email__ = "ming.chen@noaa.gov"
__date__  = "April 22, 2025"

'''
#####################################################################
# 
# generate_bern_sessions.py
#
# Purpose:
# This python script is used to handle the BERNESE sessions.
##
# History:  
#       Created by: Ming Chen 2025/04/22
#                   ming.chen@noaa.gov
# 
# Usage: python .py start_datetime end_datetime
# the datetime in %Y-%m-%dT%H:%M:%S format
#
#
#####################################################################

'''

class AIUBData():

    remote_home = 'http://ftp.aiub.unibe.ch'
    products = {
               "COD0OPSFIN":{"subdir":"CODE","pid":"COD"},
               "COD0MGXFIN":{"subdir":"CODE_MGEX/CODE","pid":"COM"},
               "COD0OPSRAP":{"subdir":"CODE","pid":"RAP"},
                }

    def __init__(self, product):
      # Check if required environment variables are set
      self.podgen_home = os.getenv('podgen_home')
      self.utils_home  = os.getenv('utils_home')
      self.local_home  = os.getenv('aiub_data')
 
      if not self.podgen_home:
         print("env is not set up, source the set_env.bash file first ..")
         sys.exit(1)
      if not AIUBData.valid_product(product):
         print("product {product} is not valid ..")
         sys.exit(1)

      self.product = product
      self.pid =  AIUBData.products[product]["pid"]
      self.NOV2022 = mkdate('20221126')

    @staticmethod
    def valid_product(product):
        valid = False
        if product in AIUBData.products: 
           valid = True
        else:
           print(f"product {product} is not valid ....")
        return valid

    def flist_after_nov2022(self, datestr, hh='00'):
        cdate = mkdate(datestr)
        yyyy = cdate.year ;  yy = cdate.year % 100
        mm = cdate.month  ; dd = cdate.day
        doy = cdate.timetuple().tm_yday
        doy = f"{doy:03d}"

        gpswd = date2gpsw(datestr)
        gweek, gday = gpswd[:4], gpswd[4:]

        flist = {}  
           
        prod =  self.product ; plink = self.pid
        if prod == 'COD0OPSFIN':
           flist = {
	            'erp': f"{prod}_{yyyy}{doy}0000_01D_01D_ERP.ERP.gz", 
	            'orb': f"{prod}_{yyyy}{doy}0000_01D_05M_ORB.SP3.gz", 
                    'clk': f"{prod}_{yyyy}{doy}0000_01D_30S_CLK.CLK.gz", 
		    'bia': f"{prod}_{yyyy}{doy}0000_01D_01D_OSB.BIA.gz"
		   }


        elif prod == 'COD0MGXFIN':
           flist = {
	            'erp': f"{prod}_{yyyy}{doy}0000_01D_12H_ERP.ERP.gz", 
	            'orb': f"{prod}_{yyyy}{doy}0000_01D_05M_ORB.SP3.gz", 
                    'clk': f"{prod}_{yyyy}{doy}0000_01D_30S_CLK.CLK.gz", 
		    'bia': f"{prod}_{yyyy}{doy}0000_01D_01D_OSB.BIA.gz"
		   }

        elif prod== 'COD0OPSRAP':
           flist = {
                    'erp': f"{prod}_{yyyy}{doy}{hh}00_01D_01D_ERP.ERP", 
		    'orb': f"{prod}_{yyyy}{doy}{hh}00_01D_05M_ORB.SP3",
	            'clk': f"{prod}_{yyyy}{doy}{hh}00_01D_30S_CLK.CLK", 
		    'bia': f"{prod}_{yyyy}{doy}{hh}00_01D_01D_OSB.BIA"
		    }
        else:

           print(f"{product} is not in the list ...")
 

        return flist  


    def flist_before_nov2022(self,  datestr, flink=None):
        gpswd = date2gpsw(datestr)
        gweek, gday = gpswd[:4], gpswd[4:]
        print(gweek, gday)
        
        cdate = mkdate(datestr)
        yyyy = cdate.year
        doy = cdate.timetuple().tm_yday
        doy = f"{doy:03d}"
        flist = {}
  
        prod =  self.product ; plink = self.pid
        if prod == 'COD0OPSFIN':
           flist = {
	            'erp': f"COD{gweek}{gday}.ERP.Z", 
	            'orb': f"COD{gweek}{gday}.EPH.Z", 
                    'clk': f"COD{gweek}{gday}.CLK.Z", 
		    'bia': f"COD{gweek}{gday}.BIA.Z"
		   }


        elif prod == 'COD0MGXFIN':
           flist = {
	            'erp': f"COM{gweek}{gday}.ERP.Z", 
	            'orb': f"COM{gweek}{gday}.EPH.Z", 
                    'clk': f"COM{gweek}{gday}.CLK.Z", 
		    'bia': f"COM{gweek}{gday}.BIA.Z"
		   }
        else:
           print(f"{product} is not in the list ...")

        return flist

    def file_path(self, datestr):
        # Construct paths
        product = self.product
        cdate = mkdate(datestr)
        yyyy = cdate.year
        doy = cdate.timetuple().tm_yday
        doy = f"{doy:03d}"
        subdir = AIUBData.products[product]['subdir']
        remote_path = f"{AIUBData.remote_home}/{subdir}"
        if 'FIN' in product:
           remote_path = f"{AIUBData.remote_home}/{subdir}/{yyyy}"
        local_path = f"{self.local_home}/{product}/{yyyy}/{doy}"
        print(yyyy, doy, subdir,self.local_home)
        return (local_path, remote_path)
	
    def file_list(self, datestr, hh='00'):
        cdate = mkdate(datestr)
        product = self.product
        if cdate <= self.NOV2022:
           flist= self.flist_before_nov2022(datestr)
        else:
           flist= self.flist_after_nov2022(datestr,hh=hh)
        return flist 
	
    def download(self, datestr, hh='00'):
        # Download files	 
        product = self.product
        local_path, remote_path = self.file_path(datestr)
        flist = self.file_list(datestr, hh=hh)
        print(f"Remote URL: {remote_path}")
        print(f"Local Data Archive Path: {local_path}")
        ftypes = ['erp','orb','clk','bia']
        for k in ftypes:
           fn  = flist[k]
           local_file = os.path.join(local_path, fn)
           if os.path.exists(local_file):
              print(f"{local_file} already exists ...")
              continue

           if not os.path.exists(local_path):
              os.makedirs(local_path)

           cmd = f"wget -q {remote_path}/{fn} -O {local_file}"
           print(cmd)
           subprocess.run(cmd, shell=True)

           # Check if the file was downloaded successfully
           if not os.path.exists(local_file):
              print(f"File download failed ...  {local_file}")

           if os.path.exists(local_file) and os.path.getsize(local_file) == 0:
              print(f"download failed ... {remote_path}/{fn}")
              os.remove(local_file)


def local_aiub_gnss(product:str, pdate:str, hh='00'):

   if not AIUBData.valid_product(product):
      sys.exit(1)
   aiub = AIUBData(product)

   local_path,_ = aiub.file_path(pdate)
   flist = aiub.file_list(pdate,hh=hh)

   flist = {k: f'{local_path}/{v}' for k, v in flist.items() } 
   return flist

def wget_aiub_gnss(product:str, pdate:str, hour=0):

   pdate = mkdate(pdate)
   hh=f'{hour:02d}'
 
   aiub = AIUBData(product)

   print(f"remote aiub url: {aiub.remote_home}")
   print(f"local aiub data home: {aiub.local_home}")
   print(f"product-date: {pdate.strftime('%Y-%m-%d')} hour: {hh}")


   # Loop over dates
   datestr = pdate.strftime("%Y%m%d")
   gpswd = date2gpsw(datestr)
   gweek = gpswd[:4]
   gday = gpswd[4:]
   print(f"cdate, GWEEK, GDAY: {pdate.strftime('%Y%m%d')} {gweek} {gday} {gpswd} ")
   aiub.download(datestr,hh=hh)

if __name__ == "__main__":
   import argparse

   parser = argparse.ArgumentParser(description='wget aiub data')
   parser.add_argument("-v","--verbose", action='store_true',  help="print info for debug")
   parser.add_argument("product", type=str,  help="CODE GNSS products: COD0OPSFIN,COD0MGXFIN,COD0OPSRAP,COD0OPSULT ")
   parser.add_argument("prod_date", type=str,  help="product date in yyyymmdd yyyydoy ")
   parser.add_argument("--hour", type=int, default=0, help="hour of the date ")
   args = parser.parse_args()
   product = args.product
   pdate = args.prod_date  
   hh=args.hour
   if not AIUBData.valid_product(product):
      sys.exit(1)
    
   wget_aiub_gnss(product, pdate, hour=hh)
 
