import os
import sys
import subprocess
import json
import FileLib
import FileSystemLib
import InventoryLib
import SystemLib

#!/usr/bin/env python3

def download_file(url, output):
    try:
        if subprocess.call(['which', 'curl'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0:
            subprocess.check_call(['curl', '-k', '-f', '--connect-timeout', '1', '-o', output, url])
        else:
            subprocess.check_call(['wget', '--no-check-certificate', '-T', '1', '-O', output, url])
    except subprocess.CalledProcessError:
        return False
    return True

def main():
    prog = os.path.basename(__file__)
    if len(sys.argv) == 2 and sys.argv[1] == "help":
        show_help(prog)

    if not callable(globals().get('ogRaiseError')):
        SystemLib.ogRaiseError(f"{prog}: it can only be executed by an ogLive client.")

    if len(sys.argv) not in [3, 4]:
        SystemLib.ogRaiseError(f"{prog} ndisk npart [adminuser]")

    ndisk, npart = sys.argv[1], sys.argv[2]
    windowsadmin = sys.argv[3] if len(sys.argv) == 4 else None

    mntdir = FileSystemLib.ogMount(ndisk, npart)
    if not mntdir:
        sys.exit(1)

    ogversion = None
    try:
        response = subprocess.check_output(['curl', '-k', '-f', '--connect-timeout', '1', '-o', '-', f'https://{ogGetServerIp()}/opengnsys/rest/info'])
        ogversion = json.loads(response).get('version')
    except subprocess.CalledProcessError:
        pass

    if not ogversion:
        SystemLib.ogRaiseError(f"GET /rest/info")

    os_type = Inventory.ogGetOsType(ndisk, npart)
    if os_type == "Windows":
        hive = FileSystemLib.ogGetHivePath(mntdir, windowsadmin)
        if not hive:
            SystemLib.ogRaiseError(f"{ndisk} {npart} {windowsadmin}/NTUSER.DAT")

        ogagentfile = f"OGAgentSetup-{ogversion.replace('pre', '')}.exe"
        tmpdir = FileLib.ogGetPath(f"{mntdir}/Windows/Temp")
        if "opengnsys agent" in InventoryLib.ogListSoftware(ndisk, npart).lower():
            print("OGAgent for Windows is already installed, you need to uninstall it before re-install.")
        else:
            if download_file(f"https://{ogGetServerIp()}/opengnsys/descargas/{ogagentfile}", f"{tmpdir}/{ogagentfile}"):
                try:
                    subprocess.check_call(['hivexsh', '-w'], input=f"""
load {hive}
cd \\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce
setval 1
Install OGAgent
string:C:\\Windows\\Temp\\{ogagentfile} /S /server {ogGetServerIp()}
commit
close
exit
""".encode())
                    print(f'Scheduled OGAgent installation after "{windowsadmin}" logon')
                    print("  (for connection problems, check configuration file).")
                except subprocess.CalledProcessError:
                    SystemLib.ogRaiseError(f"{ndisk} {npart} .../{windowsadmin}/NTUSER.DAT")
            else:
                SystemLib.ogRaiseError(f"{ndisk} {npart} /Windows/Temp/{ogagentfile}")

    elif os_type == "Linux":
        if "ogagent" in InventoryLib.ogListSoftware(ndisk, npart).lower():
            print("OGAgent for Linux is already installed, you need to uninstall it before re-install.")
        else:
            systemddir = f"{mntdir}/lib/systemd"
            if not (os.path.isdir(systemddir) and os.path.isdir(systemddir.replace('/lib', '/etc'))):
                SystemLib.ogRaiseError(f"{ndisk} {npart} systemd")

            ogagentfile = None
            code = None
            if os.path.exists(f"{mntdir}/etc/debian_version"):
                ogagentfile = f"ogagent_{ogversion.replace('pre', '')}_all.deb"
                code = f"if ! dpkg -l ogagent &>/dev/null && [ -f /var/tmp/{ogagentfile} ]; then apt-get update; apt-get install -y /var/tmp/{ogagentfile}; fi"
            elif os.path.exists(f"{mntdir}/etc/redhat-release"):
                ogagentfile = f"ogagent-{ogversion.replace('pre', '')}-1.noarch.rpm"
                code = f"if ! rpm -q ogagent &>/dev/null && [ -f /var/tmp/{ogagentfile} ]; then yum install -y /var/tmp/{ogagentfile}; fi"

            if not ogagentfile:
                SystemLib.ogRaiseError(f"{ndisk} {npart} ogagent")

            tmpdir = f"{mntdir}/var/tmp"
            if download_file(f"https://{ogGetServerIp()}/opengnsys/descargas/{ogagentfile}", f"{tmpdir}/{ogagentfile}"):
                with open(f"{systemddir}/systemd-launchogagent", 'w') as f:
                    f.write(f"""#!/bin/bash
[ $EUID = 0 ] || exit 4
start() {{
    {code}
    sed -i "0,/remote=/ s,remote=.*,remote=https://{ogGetServerIp()}/opengnsys/rest/," /usr/share/OGAgent/cfg/ogagent.cfg
    service ogagent start
}}
restart() {{
    service ogagent stop
    if [ -f /var/tmp/{ogagentfile} ]; then
        apt-get update
        apt-get install -y --reinstall /var/tmp/{ogagentfile}
    fi
    sed -i "0,/remote=/ s,remote=.*,remote=https://{ogGetServerIp()}/opengnsys/rest/," /usr/share/OGAgent/cfg/ogagent.cfg
    service ogagent start
}}

case "$1" in
    start|restart)  "$1" ;;
esac
""")
                os.chmod(f"{systemddir}/systemd-launchogagent", 0o755)

                with open(f"{systemddir}/system/launchogagent.service", 'w') as f:
                    f.write(f"""[Unit]
Description=Installing and configuring OGAgent

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-launchogagent start
TimeoutStartSec=5min

[Install]
WantedBy=multi-user.target
""")
                os.symlink(f"/lib/systemd/system/launchogagent.service", f"{systemddir.replace('/lib', '/etc')}/system/multi-user.target.wants")
                print("Scheduled OGAgent installation at next boot")
                print("  (process will be executed in the background, do not shutdown until finish).")
            else:
                SystemLib.ogRaiseError(f"{ndisk} {npart} /var/tmp/{ogagentfile}")

    elif os_type == "MacOS":
        print("OGAgent installer for macOS is not implemented yet.")
    else:
        SystemLib.ogRaiseError(f"{ndisk} {npart}")

if __name__ == "__main__":
    main()
