# ww2html.py - Wiki-wiki Text to HTML Utility



import asyncio
import sys

# These are for terminal black-magic
import contextlib
import termios

import os.path

#import TranClasses
import TranClasses as TranClasses



# this assumes Ubuntu linux
#BASEDIR = '/home/wayne'
a = os.getcwd().split('/')
BASEDIR = '/' + a[1] + '/' + a[2]

isRealTime = False

#print( 'BASEDIR:', BASEDIR )

# Global flag used to terminate all tasks.
terminate = False






def doAFile( rfn ):
  if os.path.isfile( rfn ):
    dbTran = None

    s = rfn[len(BASEDIR)+1:]
    a = s.split('/')
    sitename = a[0]

    #print( 'FileTran__init__(): ', rfn, '('+sitename+')' )

    if sitename == 'family':
      dpTran = TranClasses.TranFamily( BASEDIR, isRealTime )
    elif sitename == 'localgrown':
      dpTran = TranClasses.TranLocalGrown( BASEDIR, isRealTime )
    elif sitename == 'moodswingsband':
      dpTran = TranClasses.TranMoodSwings( BASEDIR, isRealTime )
    elif sitename == 'bleachedblondes':
      dpTran = TranClasses.TranBlondes( BASEDIR, isRealTime )
    elif sitename == 'bleachedblondes-2020':
      dpTran = TranClasses.TranBlondes2020( BASEDIR, isRealTime )
    elif sitename == 'bleachedblondes-2021':
      dpTran = TranClasses.TranBlondes2021( BASEDIR, isRealTime )
    elif sitename == 'bleachedblondes-2022-23':
      dpTran = TranClasses.TranBlondes2023( BASEDIR, isRealTime )
    #elif sitename == 'wiki':
    #  self.dpTran = TranWiki( BASEDIR )      
    else:
      #self.dpTran = None
      dpTran = TranClasses.TranWiki( BASEDIR, isRealTime )      

    if dpTran != None and os.path.isfile( rfn ):
      ty = ''
      i = rfn.rfind('.')
      if i != -1:
        ty = rfn[i:].lower()
      if ty == '.txt':
        s = dpTran.toHtml( rfn )
        #return s.encode()
      elif ty == '.ww':
        s = dpTran.wwToHtml( rfn )

      wfn = rfn[:i]+'.html'
        
      #print( rfn, wfn )
      
      if len(s) > 0:
        
        #print( s )
        
        f = open(wfn,"w")
        #f.write(s.encode())
        f.write(s)
        f.close()
        
        print('wrote to:', wfn)
      else:
        print('Did not write .html file:',wfn)

  else:
    print( "Not a file!" )




##### main() #####

async def monitor():
  global terminate

  # - Initially, we need to make a pass through all directories, looking for 
  #   .txt files that need processed. Process them when found and keep track 
  #   of where we found them.
  # - Then, one task goes back looking for more .txt files that need processed 
  #   slowly doing the job we first did.
  # - Another task focuses in on the directories where we found files that 
  #   needed processed. This task checks these directories more frequently
  #   for file changes that need processed again.
  # - Somehow there is a "kill" signal we can use to terminate the app.

  if True:
    
    rootDir = BASEDIR
    fn = os.getcwd()
    
    print('scanning:', fn )
    
    txtFiles = []
    dirs = []

    # testFile()
    async def testFile( f1 ):
      global pp
      # test file type
      ty = ''
      i = f1.rfind('.')
      if i != -1: ty = f1[i:].lower()
      # First qualification is that it is a .txt file
      if ty == '.txt' or ty == '.ww':
        f2 = f1[:len(f1)-len(ty)] + '.html'
        # second qualification is that there is a twin .html file already
        if( os.path.isfile(f2) ):
          
          # check file dates as well
          t1 = os.path.getmtime(f1)
          t2 = os.path.getmtime(f2)
          
          if t1 >= t2:
            # .txt file has been modified since .html last updated
            txtFiles.append(f1)
        
      await asyncio.sleep(0)

    # traverseDir() - function to traverse a directory (recursive)
    async def traverseDir( fn ):
      files = os.listdir( fn )
      # Pick out the .mp3 and .m4a files.
      for f in files:
        # hidden files start with '.', skip them
        if len(f) > 0 and f[0] != '.':
          # see if we have a directory
          ff = fn+'/'+f
          if os.path.isdir( ff ):
            # recurse in to pick up sub-directories
            await traverseDir( ff )
          else:
            # test for file type we are looking for
            await testFile( ff )
          #
        #
      #
      await asyncio.sleep(0)

    # processTxtFiles()
    def processTxtFiles( txtFiles ):
      for i in range(len(txtFiles)):
        
        # We are processing a .txt file, which involves testing relative
        # file references. The "current working directory" needs to be set 
        # as it would be when browsing that file.
        d = os.path.dirname(txtFiles[i])
        # Keep track of where we have found files to translate.
        if not (d in dirs):
          dirs.append( d )
        #
        os.chdir(d)


        #print('Skipping file:', txtFiles[i])
        doAFile( txtFiles[i] )
        
        
        #
        os.chdir(fn)

    # Initial traverse of the directory and processing
    await traverseDir( fn )
    processTxtFiles( txtFiles )
      
    # Continue on -- periodically checking for more files to be processed
    c2 = 0
    while( not terminate ):
      await asyncio.sleep( 1 )
      for d in dirs:
        
        #print( 'scanning: ', d )
        
        txtFiles = []        
        await traverseDir( d )
        processTxtFiles( txtFiles )
      #
      # Every 10 seconds or so, do a full traverse
      c2 += 1
      if c2 >= 10 or (c2 >= 5 and len(dirs) < 1):
        c2 = 0
        
        #print('full:', len(txtFiles))
        print( '.', end="", flush=True )
        
        await traverseDir( fn )
        processTxtFiles( txtFiles )
      #
    #
        
    terminate = True
    
    print( 'monitor() done' )


# main() - the main app
async def main():
  global terminate
  
  # - If the command-line argument specifies a directory or file, we process 
  #   the directory or file and terminate.
  
  # If cmd-line arguement specifies a dir or file, process it and be done.
  if len(sys.argv) > 1:

    rfn = os.path.abspath( sys.argv[1] )
    doAFile( rfn )
    terminate = True
    
  else:
    # Start the on-going monitor
    
    await monitor()

  print( 'main() done' )



#### Terminal Black-magic ####
# This code waits for a CTRL+D, at which point it sets "terminate" to True.
# Other tasks should pool "terminate" and finish up when True.

@contextlib.contextmanager
def raw_mode(file):
  old_attrs = termios.tcgetattr(file.fileno())
  new_attrs = old_attrs[:]
  new_attrs[3] = new_attrs[3] & ~(termios.ECHO | termios.ICANON)
  try:
    termios.tcsetattr(file.fileno(), termios.TCSADRAIN, new_attrs)
    yield
  finally:
    termios.tcsetattr(file.fileno(), termios.TCSADRAIN, old_attrs)

async def terminator():
  global terminate
  with raw_mode(sys.stdin):
    reader = asyncio.StreamReader()
    loop = asyncio.get_event_loop()
    await loop.connect_read_pipe(lambda: asyncio.StreamReaderProtocol(reader), sys.stdin)

    while not (reader.at_eof() or terminate):
      ch = await reader.read(1)
      # '' means EOF, chr(4) means EOT (sent by CTRL+D on UNIX terminals)
      if not ch or ord(ch) <= 4:
        terminate = True
        #break
      else:
        print(f'Got: {ch!r}')
    #
  #
  print( 'terminate =', terminate )


# startup() - a way to get things rolling within the asyncio environment.
async def startup():
  await asyncio.gather( main(), terminator() )

  print( 'done' )


if __name__ == "__main__":
  asyncio.run( startup() )

