import os
import sys

from engine.FileLib import *
from engine.InventoryLib import *
from engine.NetLib import *
from engine.RegistryLib import *
from engine.SystemLib import *

def ogCleanOs():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogCleanOs", "ogCleanOs int_ndisk int_nfilesys", "ogCleanOs 1 1")
        return

    # Error si no se reciben 2 parámetros.
    if len(sys.argv) != 3:
        ogRaiseError(OG_ERR_FORMAT, "ogCleanOs int_ndisk int_nfilesys")
        return

    os_type = ogGetOsType(sys.argv[1], sys.argv[2])

    if os_type == "Linux":
        # Borramos los ficheros de dispositivos y los temporales.
        ogCleanLinuxDevices(sys.argv[1], sys.argv[2])
        os.system("rm -rf " + ogMount(sys.argv[1], sys.argv[2]) + "/tmp/*")
    elif os_type == "Windows":
        # Borrar ficheros de hibernación y paginación de Windows.
        if ogGetPath(sys.argv[1], sys.argv[2], "pagefile.sys"):
            ogDeleteFile(sys.argv[1], sys.argv[2], "pagefile.sys")
        if ogGetPath(sys.argv[1], sys.argv[2], "hiberfil.sys"):
            ogDeleteFile(sys.argv[1], sys.argv[2], "hiberfil.sys")
        if ogGetPath(sys.argv[1], sys.argv[2], "swapfile.sys"):
            ogDeleteFile(sys.argv[1], sys.argv[2], "swapfile.sys")

def ogInstallMiniSetup():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogInstallMiniSetup", "ogInstallFirstBoot ogInstallRunonce")
        return

    if len(sys.argv) == 4:
        # Ejecución en el primer arranque de la máquina.
        ogInstallFirstBoot(sys.argv[1], sys.argv[2], sys.argv[3])
    elif len(sys.argv) == 7 or len(sys.argv) == 9:
        # Ejecución en el "runonce".
        ogInstallRunonce(*sys.argv[1:])
    else:
        ogRaiseError(OG_ERR_FORMAT)

def ogInstallFirstBoot():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogInstallFirstBoot", "ogInstallFirstBoot int_ndisk int_npartition str_filename", "ogInstallFirstBoot 1 1 filename.cmd")
        return

    # Error si no se reciben 3 parámetros.
    if len(sys.argv) != 4:
        ogRaiseError(OG_ERR_FORMAT)
        return

    MNTDIR = ogMount(sys.argv[1], sys.argv[2])
    if not MNTDIR:
        return

    for i in ["winnt", "windows"]:
        DIR = ogGetPath(os.path.join(MNTDIR, i, "system32"))
        if DIR:
            CMDDIR = DIR
            break
    else:
        ogRaiseError(OG_ERR_NOTFOUND, os.path.join(MNTDIR, "windows", "system32"))
        return

    CMDFILE = os.path.join(CMDDIR, sys.argv[3])

    # Creamos el archivo cmd y creamos un par de comandos para que una vez acabe la 
    # postconfiguracion resetee el mini setup, sino lo haria en cada arranque.
    with open(CMDFILE, "w") as f:
        f.write("""REG ADD HKLM\System\Setup /v SystemSetupInProgress /t REG_DWORD /d 0 /f
REG ADD HKLM\System\Setup /v CmdLine /t REG_SZ /d "" /f""")

    # Crear los valores de registro necesarios para que se haga la ejecución del .cmd al aranque.
    ogSetRegistryValue(MNTDIR, "SYSTEM", "\\Setup\\SystemSetupInProgress", 1)
    ogSetRegistryValue(MNTDIR, "SYSTEM", "\\Setup\\SetupType", 4)
    #ogDeleteRegistryValue(MNTDIR, "SYSTEM", "\\Setup\\CmdLine")
    ogAddRegistryValue(MNTDIR, "SYSTEM", "\\Setup\\CmdLine")
    ogSetRegistryValue(MNTDIR, "SYSTEM", "\\Setup\\CmdLine", "cmd.exe /c " + os.path.basename(CMDFILE))

def ogInstallRunonce():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogInstallRunonce", "ogInstallRunonce int_ndisk int_npartition str_filename str_adm_user str_adm_password bool_autologin [str_auto_user str_auto_password]", "ogInstallRunonce 1 1 filename.cmd administrator passadmin 1 userauto passuserauto", "ogInstallRunonce 1 1 filename.cmd administrator passadmin 0")
        return

    # Error si no se reciben 6 u 8 parámetros.
    if len(sys.argv) != 6 and len(sys.argv) != 8:
        ogRaiseError(OG_ERR_FORMAT)
        return

    MOUNTPOINT = ogGetPath(sys.argv[1], sys.argv[2], "/")
    CMDDIR = None

    # Comprobar que existe el directorio del fichero de comandos.
    for i in ["winnt", "windows"]:
        DIR = ogGetPath(os.path.join(MOUNTPOINT, i, "system32"))
        if DIR:
            CMDDIR = DIR
            break

    if not CMDDIR:
        ogRaiseError(OG_ERR_NOTFOUND, os.path.join(MOUNTPOINT, "Windows", "System32"))
        return

    CMDFILE = os.path.join(CMDDIR, sys.argv[3])

    if sys.argv[6] == "0":
        # Si no queremos hacer autologin despues de la postconfiguracion lo indicamos en las claves de registro
        with open(CMDFILE, "w") as f:
            f.write("""DEL C:\ogboot.*
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 0 /f
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "" /f
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /f""")
    else:
        # Si queremos hacer autologin despues de la postconfiguracion introducimos la informacion en las claves de registro
        with open(CMDFILE, "w") as f:
            f.write(f"""DEL C:\ogboot.*
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 1 /f
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "{sys.argv[7]}" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /t REG_SZ /d "{sys.argv[8]}" /f""")

    # Creamos las claves de registro necesarias para que meter el cmd en el runonce del usuario y este haga autologin
    ogAddRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows\\CurrentVersion\\RunOnce\\PostConfiguracion")
    ogSetRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows\\CurrentVersion\\RunOnce\\PostConfiguracion", f"C:\\windows\\system32\\{sys.argv[3]}")
    ogAddRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AutoAdminLogon")
    ogSetRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AutoAdminLogon", "1")
    ogAddRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultUserName")
    ogSetRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultUserName", sys.argv[4])
    ogAddRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultDomainName")
    ogSetRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultDomainName", ".\\")
    ogAddRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultPassword")
    ogSetRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultPassword", sys.argv[5])
    ogDeleteRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\ForceAutoLockOnLogon")
    ogDeleteRegistryValue(MOUNTPOINT, "software", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AutoLogonCount")

def ogAddCmd():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogAddCmd", "ogAddCmd int_ndisk int_npartition str_filename str_commands", "ogAddCmd 1 1 filename.cmd command")
        return

    # Error si no se reciben 4 parámetros.
    if len(sys.argv) != 5:
        ogRaiseError(OG_ERR_FORMAT)
        return

    MOUNTPOINT = ogMount(sys.argv[1], sys.argv[2])
    if not MOUNTPOINT:
        return

    # Crear fichero de comandos, si no existe.
    CMDFILE = ogGetPath(os.path.join(MOUNTPOINT, "windows", "system32"), sys.argv[3])
    if not CMDFILE:
        ogInstallMiniSetup(sys.argv[1], sys.argv[2], sys.argv[3])
        CMDFILE = ogGetPath(os.path.join(MOUNTPOINT, "windows", "system32"), sys.argv[3])
        if not CMDFILE:
            ogRaiseError(OG_ERR_NOTFOUND, os.path.join(MOUNTPOINT, "windows", "system32", sys.argv[3]))
            return

    # Concatenamos el comando en el fichero de comandos
    with open(CMDFILE, "a") as f:
        f.write(sys.argv[4])

def ogDomainScript():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogDomainScript", "ogDomainScript int_ndisk int_npartition str_filename str_domain str_user str_password", "ogDomainScript 1 1 filename.cmd domain user password_user")
        return

    # Error si no se reciben 6 parámetros.
    if len(sys.argv) != 7:
        ogRaiseError(OG_ERR_FORMAT)
        return

    MOUNTPOINT = ogMount(sys.argv[1], sys.argv[2])
    if not MOUNTPOINT:
        return

    # Comprobar que existe el directorio de comandos.
    CMDDIR = ogGetPath(os.path.join(MOUNTPOINT, "windows", "system32"))
    if not CMDDIR:
        ogRaiseError(OG_ERR_NOTFOUND, os.path.join(sys.argv[1], "windows", "system32"))
        return

    # Añadimos en el cmd que se ejecutara al arranque, el comando de ejecutar el script que añade al dominio.
    ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], "CSCRIPT joindomain.vbs")
    # Eliminamos el script porque tiene el usuario de administrador de dominio en claro
    ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], "DEL /Q C:\\Windows\\System32\\joindomain.vbs")
    # Metemos unas claves de registro para que el dominio salga seleccionado por defecto
    ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], f"REG ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v DefaultDomainName /t REG_SZ /d \"{sys.argv[4]}\" /f")

    # Creamos el archivo joindomain.vbs que nos introduce la maquina en el dominio
    with open(os.path.join(CMDDIR, "joindomain.vbs"), "w") as f:
        f.write(f"""Const JOIN_DOMAIN = 1
Const ACCT_CREATE = 2
Const ACCT_DELETE = 4
Const WIN9X_UPGRADE = 16
Const DOMAIN_JOIN_IF_JOINED = 32
Const JOIN_UNSECURE = 64
Const MACHINE_PASSWORD_PASSED = 128
Const DEFERRED_SPN_SET = 256
Const INSTALL_INVOCATION = 262144

strDomain = "{sys.argv[4]}"
strUser = "{sys.argv[5]}"
strPassword = "{sys.argv[6]}"

Set objNetwork = CreateObject("WScript.Network")
strComputer = objNetwork.ComputerName

Set objComputer = GetObject("winmgmts:{{impersonationLevel=Impersonate}}!\\\\\" & _
    strComputer & "\\root\\cimv2:Win32_ComputerSystem.Name='" & strComputer & "'")

ReturnValue = objComputer.JoinDomainOrWorkGroup(strDomain, strPassword, _
    strDomain & "\\" & strUser, NULL, JOIN_DOMAIN + ACCT_CREATE)""")
        
def ogConfigureOgagent():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogConfigureOgagent", "ogConfigureOgagent int_ndisk int_nfilesys", "ogConfigureOgagent 1 1")
        return

    # Error si no se reciben 2 parámetros.
    if len(sys.argv) != 3:
        ogRaiseError(OG_ERR_FORMAT, "ogConfigureOgagent int_ndisk int_nfilesys")
        return

    MNTDIR = ogMount(sys.argv[1], sys.argv[2])
    if not MNTDIR:
        return

    # Comprobar si existe el fichero de configuración de OGAgent.
    for AGENTDIR in ["usr/share/OGAgent", "Program Files/OGAgent", "Program Files (x86)/OGAgent", "Applications/OGAgent.app"]:
        CFGFILE = ogGetPath(os.path.join(MNTDIR, AGENTDIR, "cfg", "ogagent.cfg"))
        if CFGFILE:
            break
    else:
        ogRaiseError(OG_ERR_NOTFOUND, "ogagent.cfg")
        return

    # Parchear dirección del servidor OpenGnsys en el fichero de configuración de OGAgent.
    with open(CFGFILE, "r") as f:
        lines = f.readlines()
    with open(CFGFILE, "w") as f:
        for line in lines:
            if line.startswith("remote="):
                line = "remote=https://" + ogGetServerIp() + "/opengnsys/rest/\n"
            f.write(line)

def ogInstallLaunchDaemon():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogInstallLaunchDaemon", "ogInstallLaunchDaemon int_ndisk int_nfilesys str_scriptname", "ogInstallLaunchDaemon 1 2 postconf")
        return

    # Error si no se reciben 3 parámetros.
    if len(sys.argv) != 4:
        ogRaiseError(OG_ERR_FORMAT)
        return

    LAUNCHDIR = ogGetPath(sys.argv[1], sys.argv[2], "/Library/LaunchDaemons")
    if not LAUNCHDIR:
        ogRaiseError(OG_ERR_NOTFOUND, os.path.join(sys.argv[1], sys.argv[2], "/Library/LaunchDaemons"))
        return

    SCRIPTDIR = ogGetPath(sys.argv[1], sys.argv[2], "/usr/share")
    if not SCRIPTDIR:
        ogRaiseError(OG_ERR_NOTFOUND, os.path.join(sys.argv[1], sys.argv[2], "/usr/share"))
        return

    # Crear fichero de configuración del servicio de arranque.
    with open(os.path.join(LAUNCHDIR, f"es.opengnsys.{sys.argv[3]}.plist"), "w") as f:
        f.write("""<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
        <dict>
                <key>Label</key>
                <string>es.opengnsys.{}</string>
                <key>ProgramArguments</key>
                <array>
                        <string>{}/{}.sh</string>
                </array>
                <key>RunAtLoad</key>
                <true/>
                <key>StandardOutPath</key>
                <string>/var/log/{}.log</string>
                <key>StandardErrorPath</key>
                <string>/var/log/{}.err</string>
                <true/>
        </dict>
</plist>""".format(sys.argv[3], SCRIPTDIR, sys.argv[3], sys.argv[3], sys.argv[3]))

    # Crear un fichero de script vacío.
    with open(os.path.join(SCRIPTDIR, f"{sys.argv[3]}.sh"), "w") as f:
        f.write("")
    os.chmod(os.path.join(SCRIPTDIR, f"{sys.argv[3]}.sh"), 0o755)

def ogAddToLaunchDaemon():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogAddToLaunchDaemon", "ogAddToLaunchDaemon int_ndisk int_nfilesys str_scriptname str_command", "ogAddToLaunchDaemon 1 2 postconf \"diskutil enableJournal disk0s2\"")
        return

    # Error si no se reciben 4 parámetros.
    if len(sys.argv) != 5:
        ogRaiseError(OG_ERR_FORMAT)
        return

    SCRIPTDIR = ogGetPath(sys.argv[1], sys.argv[2], "/usr/share")
    if not SCRIPTDIR:
        ogRaiseError(OG_ERR_NOTFOUND, os.path.join(sys.argv[1], sys.argv[2], "/usr/share"))
        return

    # Comprobar que existe el fichero de comandos.
    SCRIPTFILE = os.path.join(SCRIPTDIR, sys.argv[3] + ".sh")
    if not os.path.exists(SCRIPTFILE):
        ogRaiseError(OG_ERR_NOTFOUND, SCRIPTFILE)
        return

    # Concatenamos el comando en el fichero de comandos
    with open(SCRIPTFILE, "a") as f:
        f.write(sys.argv[4] + "\n")

def ogUninstallLinuxClient():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogUninstallLinuxClient", "ogUninstallLinuxClient int_ndisk int_filesys", "ogUninstallLinuxClient 1 1")
        return

    # Error si no se reciben 2 parámetros.
    if len(sys.argv) != 3:
        ogRaiseError(OG_ERR_FORMAT)
        return

    MNTDIR = ogMount(sys.argv[1], sys.argv[2])
    if not MNTDIR:
        return

    # Borrar ficheros y quitar llamada al cliente durante el proceso de inicio.
    os.system(f"rm -f {MNTDIR}/{{usr/sbin,sbin,usr/local/sbin}}/ogAdmLnxClient")
    os.system(f"rm -f {MNTDIR}/{{etc,usr/local/etc}}/ogAdmLnxClient.cfg")
    os.system(f"sed -i -e '/ogAdmLnxClient/ d' {MNTDIR}/{{etc,usr/local/etc}}/{{rc.local,rc.d/rc.local}} 2>/dev/null")

def ogUninstallWindowsClient():
    # Si se solicita, mostrar ayuda.
    if len(sys.argv) > 1 and sys.argv[1] == "help":
        ogHelp("ogUninstallWindowsClient", "ogUninstallWindowsClient int_ndisk int_filesys str_filename", "ogUninstallWindowsClient 1 1 filename.cmd")
        return

    # Error si no se reciben 3 parámetros.
    if len(sys.argv) != 4:
        ogRaiseError(OG_ERR_FORMAT)
        return

    MNTDIR = ogMount(sys.argv[1], sys.argv[2])
    if not MNTDIR:
        return

    # Crear órdenes para desinstalar servicio y borrar ejecutable del cliente.
    if ogGetPath(MNTDIR, "windows", "ogAdmWinClient.exe") or ogGetPath(MNTDIR, "winnt", "ogAdmWinClient.exe"):
        ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], 'ogAdmWinClient -remove')
        ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], 'DEL C:\\Windows\\ogAdmWinClient.exe')
        ogAddCmd(sys.argv[1], sys.argv[2], sys.argv[3], 'DEL C:\\Winnt\\ogAdmWinClient.exe')