#!/usr/bin/python3

import os
import sys
import time
import subprocess
import shutil

import ogGlobals
import SystemLib
import FileSystemLib
import DiskLib
import NetLib
import StringLib
import FileLib
import ImageLib

#Descripcion:
# Si Repositorio es el global (REPO) realiza un deploy.
# Si Repositorio es local (CACHE) realiza un restoreImage CACHE
# El deploy, si detecta que el cliente no tiene una CACHE o no tiene espacio suficiente consulta el engine.cfg  RESTOREPROTOCOLNOCACHE

prog = os.path.basename (sys.argv[0])

def main (repo, imgname, disk, par, proto='UNICAST', protoopt=''):
    if repo: repo = repo.upper()
    else:    repo = 'REPO'
    proto    = proto.upper()
    protoopt = protoopt.upper()
    time1 = time.time()

# Clear temporary file used as log track by httpdlog
# Limpia los ficheros temporales usados como log de seguimiento para httpdlog
    with open (ogGlobals.OGLOGCOMMAND, 'w') as fd:
        fd.write (' ')
    if 'EjecutarScript' != SystemLib.ogGetCaller():
        with open (ogGlobals.OGLOGSESSION, 'w') as fd:
            fd.write ('')

# Registro de inicio de ejecución
    SystemLib.ogEcho (['log', 'session'], None, f'[1] {ogGlobals.lang.MSG_SCRIPTS_START} {prog} {" ".join(sys.argv)}')

# Si el origen(pariticion) esta bloqueada salir.
    if FileSystemLib.ogIsLocked (disk, par):
        SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_PARTITION}, {disk} {par}')
        sys.exit (1)

    SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_HELP_ogUnmount} {disk} {par}')
    FileSystemLib.ogUnmount (disk, par)

# Valor por defecto para el repositorio.
    mode = None
    if NetLib.ogGetIpAddress() == repo or 'CACHE' == repo:
        mode = 'CACHE'
    else:
        if StringLib.ogCheckIpAddress (repo) or 'REPO' == repo:
            if not NetLib.ogChangeRepo (repo):
                SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, repo)
                sys.exit (1)
            mode = 'REPO'

#Informacioin previa de la imagen
    if mode:
        imgpath = FileLib.ogGetPath (src=mode, file=f'{imgname}.img')
    else:
        imgpath = FileLib.ogGetPath (file=f'{imgname}.img')
    imgos = ImageLib.ogGetImageInfo (imgpath)
    #if   imgos == 1: sys.exit(SystemLib.ogRaiseError("session", OG_ERR_NOTFOUND, f"{repo} {imgname}"))
    #elif imgos == 5: sys.exit(SystemLib.ogRaiseError("session", OG_ERR_IMAGEFILE, f"{repo} {imgname}"))
    #elif imgos != 0: sys.exit(SystemLib.ogRaiseError("session", OG_ERR_GENERIC))
    if not imgos:
        SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_GENERIC, '')
        sys.exit (1)

    imgsize = os.path.getsize (imgpath) // 1024
    SystemLib.ogEcho (['log', 'session'], None, f'[1] REPO={repo} IMG-FILE={imgname}.img  SIZE={imgsize} (KB)   METADATA={imgos}')

# Procesar repositorio.
    if 'CACHE' == mode:
        nextoperation = 'CACHE'
    elif 'REPO' == mode:
        if 'MULTICAST-DIRECT' == proto:
            nextoperation = 'MULTICAST'
        elif 'UNICAST-DIRECT' == proto:
            nextoperation = 'UNICAST'
            # Si protocolo es torrent|torrent-cache o multicast|multicast-cache
        elif proto in ['TORRENT', 'TORRENT-CACHE', 'MULTICAST', 'MULTICAST-CACHE', 'UNICAST', 'UNICAST-CACHE']:
		# Eliminamos CACHE o DIRECT
            proto = proto.split ('-')[0]
            SystemLib.ogEcho (['log', 'session'], None, f'[2] updateCache {repo} "/{imgname}.img" {proto} {protoopt}')
            time2 = time.time()
            retval = subprocess.run (['updateCache.py', repo, f'/{imgname}.img', proto, protoopt]).returncode
            time2 = time.time() - time2
            SystemLib.ogEcho (['log', 'session'], None, f'   [ ]  {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} updateCache {int (time2/60)}m {int (time2%60)}s')
            if 0 == retval:
                SystemLib.ogEcho (['log', 'session'], None, '[50] updateCache (OK)')
                nextoperation = 'CACHE'
            elif retval in [15, 16]:
                        # no se permite usar la cache (no existe(15) o no espacio sufiente (16). Se consulta engine.cfg para RESTOREPROTOCOLNOCACHE [ multicast   unicast  none ]
                SystemLib.ogEcho (['log', 'session'], None, f'[50] {ogGlobals.lang.MSG_ERR_NOTCACHE} ;  {ogGlobals.lang.MSG_ERR_CACHESIZE}')
                SystemLib.ogEcho (['log', 'session'], None, f'[50] {ogGlobals.lang.MSG_SCRIPTS_CHECK_ENGINE}:  RESTOREPROTOCOLNOTCACHE={ogGlobals.RESTOREPROTOCOLNOTCACHE}')
                if 'MULTICAST' == RESTOREPROTOCOLNOTCACHE:
                    if 'MULTICAST' == proto: nextoperation = 'MULTICAST'
                    elif 'TORRENT' == proto: nextoperation = 'UNICAST'
                    elif 'UNICAST' == proto: nextoperation = 'UNICAST'
                elif 'UNICAST' == RESTOREPROTOCOLNOTCACHE:
                    nextoperation = 'UNICAST'
                elif RESTOREPROTOCOLNOTCACHE is None:
                    if 15 == retval:
                        SystemLib.ogEcho (['log', 'session'], None, f'[100] {ogGlobals.lang.MSG_ERR_NOTCACHE}')
                        SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_NOTCACHE, 'NOT CACHE')
                        sys.exit (1)
                    elif 16 == retval:
                        SystemLib.ogEcho (['log', 'session'], None, f'[100]  {ogGlobals.lang.MSG_ERR_CACHESIZE}')
                        SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, 'CACHE FULL')
                        sys.exit (1)
            elif retval in [57, 60]:
			# Time-out en la transferencia multicast (El mensaje de error está enviado)
                sys.exit (retval)
            else:
			# Error desconocido
                sys.exit (retval)
        else:
            SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_ERR_FORMAT}, {proto}')
            sys.exit (1)
    else:
        SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_ERR_FORMAT}, {repo}')
        sys.exit (1)

    time3 = time.time()

# Obtener parámetros de restauración.
    if 'CACHE' == nextoperation:
        params = ['CACHE', imgname, disk, par]
    elif 'UNICAST' == nextoperation:
        params = [repo, imgname, disk, par]
    elif 'MULTICAST' == nextoperation:
        params = [repo, imgname, disk, par, proto, protoopt]

# Si existe, ejecuta script personalizado "restoreImageCustom"; si no, llama al genérico "restoreImage".
    if shutil.which ('restoreImageCustom'):
        SystemLib.ogEcho (['log', 'session'], None, f'[55] {ogGlobals.lang.MSG_HELP_ogRestoreImage}: restoreImageCustom {params}')
        retval = subprocess.run (['restoreImageCustom'] + params).returncode
    else:
        SystemLib.ogEcho (['log', 'session'], None, f'[55] {ogGlobals.lang.MSG_HELP_ogRestoreImage}: restoreImage {params}')
        retval = subprocess.run (['restoreImage.py'] + params).returncode

# Mostrar resultados.
    resumerestoreimage = subprocess.run (['grep', '--max-count', '1', 'Total Time:', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout
    SystemLib.ogEcho (['log', 'session'], None, f'   [ ]      {resumerestoreimage} ')
# Si la transferencia ha dado error me salgo.
    if retval:
        SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_IMAGE, f'{repo} {imgname}')
        if SystemLib.ogGetCaller() != 'EjecutarScript':
            SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_INTERFACE_END} {ogGlobals.OG_ERR_IMAGE}')
        sys.exit (ogGlobals.OG_ERR_IMAGE)

    time3 = time.time() - time3
    SystemLib.ogEcho (['log', 'session'], None, f'   [ ]      {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} : {int (time3/60)}m {int (time3%60)}s')

# Si existe, ejecuta script personalizado de postconfiguración "configureOsCustom"; si no, llama al genérico "configureOs".
    if shutil.which ('configureOsCustom'):
        SystemLib.ogEcho (['log', 'session'], None, '[90] configureOsCustom')
        subprocess.run (['configureOsCustom', disk, par, repo, imgname])
    else:
        SystemLib.ogEcho (['log', 'session'], None, f'[90] {ogGlobals.lang.MSG_SCRIPTS_OS_CONFIGURE}')
        subprocess.run (['configureOs.py', disk, par])

    time_total = time.time() - time1
    SystemLib.ogEcho (['log', 'session'], None, f'[100] {ogGlobals.lang.MSG_SCRIPTS_TIME_TOTAL} {int (time_total/60)}m {int (time_total%60)}s')

# Registro de fin de ejecución
# Si se ha llamado desde ejecutar script no lo muestro para no repetir.
    if SystemLib.ogGetCaller() != 'EjecutarScript':
        SystemLib.ogEcho (['log', 'session'], None, f'{ogGlobals.lang.MSG_INTERFACE_END} {retval}')
        sys.exit (retval)

if __name__ == '__main__':
    if len (sys.argv) < 6:
        SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} REPO imagen ndisco nparticion [ UNICAST-DIRECT|UNICAST|UNICAST-CACHE|MULTICAST-DIRECT|MULTICAST|MULTICAST-CACHE|TORRENT [opciones protocolo] ]')
        sys.exit (1)
    main (*sys.argv[1:])
