#!/usr/bin/python3

import os
import sys
import time
import subprocess

import ogGlobals
import SystemLib
import NetLib
import StringLib
import DiskLib
import CacheLib
import FileLib
import PostConfLib
import ImageLib
import FileSystemLib
import InventoryLib
import UEFILib

#/**
#@file    createImage
#@brief   Scirpt de ejemplo para crear una imagen de un sistema de archivos.
#@brief   Se usa como base para el programa de creación de imágenes de OpenGnsys Admin).
#@param 1 disco 
#@param 2 particion 
#@param 3 REPO|CACHE
#@param 4 imagen
#@return  
#@exception OG_ERR_FORMAT     # 1 formato incorrecto.
#@exception OG_ERR_PARTITION  # 3 Error en partición de disco o en su sistema de archivos
#@exception OG_ERR_IMAGE      # 5 Error en funcion ogCreateImage o ogRestoreImage.
#@exception OG_ERR_NOTWRITE   # 14 error de escritura
#@exception OG_ERR_NOTCACHE   # 15 si cache no existe 15
#@exception OG_ERR_CACHESIZE  # 16 si espacio de la cache local o remota no tiene espacio 16
#@exception OG_ERR_REDUCEFS   # 17 error al reducir sistema de archivos.
#@exception OG_ERR_EXTENDFS   # 18 Errror al expandir el sistema de archivos.
#@note   
#@todo: que hacer, si el tamaño de la cache es sufciente, pero no tiene espacio libre
#@todo: que hacer, si hay una imagen con igual nombre en la cache
#*/ ##

# Test 1.  crear una imagen en un REPO sin espacio libre. 
# test 2.  crear una imagen en un REPO en modo solo lectura.
# test 3.  intentar crear una imagen en la cache de un equipo que no la disponga.
# test 4.  crear una imagen en la Cache sin espacio sufiente. 
# test 5.  intentar crear una imagen, en la que no se puede reducir el FS.

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

def main (disk, par, repo, imgname):
    time1 = time.time()

    imgext = getattr (ogGlobals, 'IMGEXT')
    if not imgext: imgext = 'img'
    repo = repo.upper()

#Load engine configurator from engine.cfg file.
#Carga el configurador del engine desde el fichero engine.cfg

# Valores por defecto en etc/engine.cfg

# Clear temporary file used as log track by httpdlog
# Limpia los ficheros temporales usados como log de seguimiento para httpdlog
# salvo si es llamado desde createImageCustom
    if 'createImageCustom' != SystemLib.ogGetCaller():
        with open (ogGlobals.OGLOGSESSION,          'w') as fd: fd.write ('')
        with open (ogGlobals.OGLOGCOMMAND,          'w') as fd: fd.write ('')
        with open (f'{ogGlobals.OGLOGCOMMAND}.tmp', 'w') as fd: fd.write ('')

    SystemLib.ogEcho (['log', 'session'], None, f'[1] {ogGlobals.lang.MSG_SCRIPTS_START} {" ".join(sys.argv)}')

# Si es una ip y es igual a la del equipo restaura desde cache
    if NetLib.ogGetIpAddress() == repo:
        repo = 'CACHE'
    if StringLib.ogCheckIpAddress (repo) or 'REPO' == repo:
        if not NetLib.ogChangeRepo (repo):
            SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, repo)
            sys.exit (1)
        repo = 'REPO'

# Si el repositorio es CACHE comprobamos que exista
    if 'CACHE' == repo:
        if not CacheLib.ogFindCache():
            SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTCACHE, 'CACHE')
            sys.exit (1)

# Obtener información de los parámetros de entrada.
    PART = DiskLib.ogDiskToDev (disk, par)
    if not PART:
        SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}')
        sys.exit (1)

#Comprobamos acceso de escritura.
    dirtemp = time.strftime ('%Y%m%d-%H%M%S', time.gmtime())
    if not FileLib.ogMakeDir (container=repo, file=f'/{imgname}{dirtemp}'):
        SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTWRITE, repo)
        FileLib.ogDeleteTree (repo, f'/{imgname}{dirtemp}')
        sys.exit (1)

    imgdir = FileLib.ogGetParentPath (src=repo, file=f'/{imgname}')
    if not imgdir:
        dn = os.path.dirname (f'/{imgname}')
        SystemLib.ogEcho (['log', 'session'], None, f'[5] {ogGlobals.lang.MSG_HELP_ogMakeDir} "{repo} {dn}"')
        if not FileLib.ogMakeDir (container=repo, file=dn):
            SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTWRITE, f'{repo} /{imgname}')
            sys.exit (1)
        imgdir = FileLib.ogGetParentPath (src=repo, file=f'/{imgmame}')
        if not imgdir:
            SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTWRITE, f'{repo} /{imgname}')
            sys.exit (1)
    bn = os.path.basename (f'/{imgname}')
    imgfile = f'{imgdir}/{bn}.{imgext}'

    with open (ogGlobals.OGLOGCOMMAND, 'w') as fd: fd.write ('')
    PostConfLib.ogCleanOs (disk, par)

#Comprobar espacio que requerira la imagen para ser almacenada
    sizedata, sizerequired, sizefree, isenoughspace = ImageLib.ogGetSizeParameters (disk, par, repo, imgname)
    SystemLib.ogEcho (['log', 'session'], None, f'[16] {prog} {ogGlobals.lang.MSG_SCRIPTS_CREATE_SIZE} {sizerequired} {sizefree}')
    if not isenoughspace:
        SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_CACHESIZE, repo)
        sys.exit (1)

# Comprobar consistencia del sistema de archivos.
    with open (ogGlobals.OGLOGCOMMAND, 'w') as fd: fd.write ('')
    sizefs = FileSystemLib.ogGetFsSize (disk, par)
    SystemLib.ogEcho (['log', 'session'], None, f'[20] {ogGlobals.lang.MSG_HELP_ogCheckFs} {par} {sizefs} (KB)')
    FileSystemLib.ogUnmount (disk, par)
    if not FileSystemLib.ogCheckFs (disk, par):
        SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'ogCheckFs {disk} {par}')
        sys.exit (1)

# Si es UEFI copio el cargador de arranque a la partición
    ostype = InventoryLib.ogGetOsType (disk, par)
    if InventoryLib.ogIsEfiActive() and 'Windows' == ostype:
        SystemLib.ogEcho (['log', 'session'], None, f'[25] {ogGlobals.lang.MSG_HELP_ogCopyEfiBootLoader}')
        UEFILib.ogCopyEfiBootLoader (disk, par)

# Evaluar variable de engine.cfg para reducir el sistema de archivos en la creacion
    if ogGlobals.IMGREDUCE:
        SystemLib.ogEcho (['log', 'session'], None, f'[30] {ogGlobals.lang.MSG_HELP_ogReduceFs}')
        FileSystemLib.ogReduceFs (disk, par)
        newsizefs = FileSystemLib.ogGetFsSize (disk, par)
        timeaux = time.time() - time1
        SystemLib.ogEcho (['log', 'session'], None, f'      {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} ( {newsizefs} KB ) : {int (timeaux/60)}m {int (timeaux%60)}s')

# Renombrar el fichero de imagen si ya existe.
    if os.path.exists (imgfile):
        SystemLib.ogEcho (['log', 'session'], None, f'[35] {ogGlobals.lang.MSG_SCRIPTS_FILE_RENAME} "{imgfile}" -> "{imgfile}.ant".')
        os.rename (imgfile,               f'{imgfile}.ant')
    if os.path.exists (f'{imgfile}.torrent'):  os.rename (f'{imgfile}.torrent',  f'{imgfile}.torrent.ant')
    if os.path.exists (f'{imgfile}.sum'):      os.rename (f'{imgfile}.sum',      f'{imgfile}.sum.ant')
    if os.path.exists (f'{imgfile}.full.sum'): os.rename (f'{imgfile}.full.sum', f'{imgfile}.full.sum.ant')

# Crear la imagen.
    with open (ogGlobals.OGLOGCOMMAND, 'w') as fd: fd.write ('')
    time2 = time.time()
    SystemLib.ogEcho (['log', 'session'], None, f'[40] {ogGlobals.lang.MSG_HELP_ogCreateImage} : ogCreateImage {disk} {par} {repo} {imgname} {ogGlobals.IMGPROG} {ogGlobals.IMGCOMP}')
    if not ImageLib.ogCreateImage (disk, par, repo, f'/{imgname}', ogGlobals.IMGPROG, ogGlobals.IMGCOMP):
        SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, 'ogCreateImage')
        sys.exit (1)
    resumecreateimage = subprocess.run (['grep', 'Total Time:', ogGlobals.OGLOGCOMMAND], capture_output=True, text=True).stdout
    timeaux2 = time.time() - time2
    SystemLib.ogEcho (['log', 'session'], None, f'      {resumecreateimage} ')
    SystemLib.ogEcho (['log', 'session'], None, f'      {ogGlobals.lang.MSG_SCRIPTS_TIME_PARTIAL} : {int (timeaux2/60)}m {int (timeaux2%60)}s')

# Extender sistema de archivos
    time3 = time.time()
    SystemLib.ogEcho (['log', 'session'], None, f'[90] Extender sistema de archivos.')
    if not FileSystemLib.ogExtendFs (disk, par):
        SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_EXTENDFS, f'{disk} {par}')
        sys.exit (1)
    sizefs2 = FileSystemLib.ogGetFsSize (disk, par)
    timeaux3 = time.time() - time3
    SystemLib.ogEcho (['log', 'session'], None, f'      {ogGlobals.lang.MSG_HELP_ogExtendFs}  {newsizefs} ->  {sizefs} = {sizefs2}: {int (timeaux3/60)}m {int (timeaux3%60)}s')

#TODO que hacer si error al extender sistemade archivos

#resumen de la operacion
    p = FileLib.ogGetPath (src=repo, file=f'/{imgname}.{imgext}')
    ls_out = subprocess.run (['ls', '-s', p], capture_output=True, text=True).stdout
    imgsize = ls_out.split()[0]
    imgos = ImageLib.ogGetImageInfo (p)

    t = time.time() - time1
    SystemLib.ogEcho (['log', 'session'], None, f'[100] {ogGlobals.lang.MSG_SCRIPTS_TIME_TOTAL} {int (t/60)}m {int (t%60)}s')
    SystemLib.ogEcho (['log', 'session'], None, f'      FileSystem {PART} with {newsizefs} KB data created onto file-image as {imgname} and used {imgsize} KB')
    SystemLib.ogEcho (['log', 'session'], None, f'      Image-file {imgname} metadata: {imgos}')

if __name__ == '__main__':
    if 5 != len (sys.argv):
        SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_FORMAT, f'{ogGlobals.lang.MSG_FORMAT}: {prog} ndisco nparticion REPO|CACHE imagen')
        sys.exit (1)
    main (*sys.argv[1:])

