#!/usr/bin/ardipython

import argparse
import platform
import shutil
import sys
#import pycurl
import os
from subprocess import call
import traceback
import xmltodict
import requests

def GetSiteList(remotehost):
    try:		
        #buf = StringIO()
        
        url = 'http://' + remotehost + '/api/connect';
        print("Requesting Site List From: " + url)
        
        web = requests.get(url,timeout=5)
        
        s = web.text

        try:
            siteset = []
            result = xmltodict.parse(s)
            #print(str(result))
            try:
                sites = result['ardi']['sites']            
                try:
                    sn = sites['subsite']['@url']
                    siteset.append((sn,sites['subsite']['#text']))
                except:
                    for st in sites['subsite']:
                        siteset.append((st['@url'],st['#text']))
            except:
                traceback.print_exc()
                return [('default','default')]
        except:
            return [('default','Default')]

        #print(str(siteset))

        return siteset
    
    except:
        print("Failed To Get ARDI Site List")
        traceback.print_exc()
        return []

def GetDriverList(remotehost):    
    try:
        #buf = StringIO()
        
        url = 'http://' + remotehost + '/api/drivers';
        #print(url)       
        web = requests.get(url,timeout=5)
        s = web.text

        result = xmltodict.parse(s)

        try: 
            return [(int(result['drivers']['driver']['@port']),result['drivers']['driver']['@drv'])]
        except:
            lst = []
            try:
                for drv in result['drivers']['driver']:
                    lst.append((int(drv['@port']),drv['@drv']))
                            
                return lst
            except:
                print("Driver Details Empty")
                return []
    except:
        print("Failed To Get ARDI Driver Details")
        #traceback.print_exc()
        return []
    
parser = argparse.ArgumentParser(description="Perform Actions on All ARDI Drivers")
parser.add_argument('server',help='The URL of your ARDI instance')
parser.add_argument('mode',help='Choose between \'install\' and \'remove\'')
parser.add_argument('--driver',help='Choose only a specific driver type to act on')
parser.add_argument('--skip',help='Skip a driver based on port number')
parser.add_argument('-d',action='store_true',help='Do not attempt to start consolidators')
    
import ctypes, os
try:
    is_admin = os.geteuid() == 0
except AttributeError:
    is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0
    
if is_admin == False:
    print("Error: This must be run as root/an Administrator")
    sys.exit(0)  

args = parser.parse_args()

skip = ""
if args.skip is not None:
    skip = args.skip
    
#Override
server=args.server
mode = args.mode
driver = ""
if args.driver is not None:
    driver = args.driver
    print("Restart Restricted To " + driver + " drivers")

if ((mode != 'remove') and (mode != 'install')):
    print("Invalid Mode Selected")
    sys.exit(-1)

server = server.replace("localhost","127.0.0.1")

siteset = [server]

if server[len(server)-1] == '*':
    host = server[0:len(server)-1]
    sites = GetSiteList(host)
    #print(str(sites))
    siteset = []
    for n in sites:
        siteset.append(host + "/s/" + n[0])

for server in siteset:
    #Get Driver Information
    print("Checking ARDI Site: " + server)
    drivers = GetDriverList(server)

    sitename = "default"
    n = server.rfind('/')
    if n > 0:
        sitename = server[n+1:]

    print("This Site Name: " + sitename)
    
    startcon = True
    if driver != "":
        startcon = False
    try:
        if args.d == True:
            startcon = False
    except:
        pass

    conpath = "/opt/ardi/srv/consolidator/ardiconsolidators"
    alarmpath = "/opt/ardi/srv/alarmmanager/alarminstaller"
    storagepath = "/opt/ardi/web/sites/" + sitename + "/drivers.install"
    supervisorpath = "/opt/ardi/supervisor.d/" + sitename + ".conf"

    if os.name == "nt":
        pypath = os.getenv('ARDIPythonPath') + ".exe"
        basepath = os.getcwd() + "\\"

        conpath = os.path.abspath(basepath + "..\\services\\consolidator\\ardiconsolidators.py")
        alarmpath = os.path.abspath(basepath + "..\\services\\alarmmanager\\alarminstaller.py")
        storagepath = os.path.abspath(basepath + "..\\web\\sites\\" + sitename + "\\drivers.install")
        supervisorpath = os.path.abspath(basepath + "supervisor.d\\" + sitename + ".conf")
    else:
        try:
            pypath = os.getenv('ARDIPythonPath')
        except:
            pypath = "python3"
            
        if pypath is None:
            pypath = "python3"
        
    try:
        if os.path.exists(conpath) == False:
            startcon = False
    except:
        startcon = False

    try:
        os.makedirs(os.path.dirname(storagepath))
    except:
        pass

    try:
        print("Building: " + os.path.dirname(supervisorpath))
        os.makedirs(os.path.dirname(supervisorpath))
    except:
        pass

    added = []

    if (mode == 'remove'):    
        if startcon == True:
            #Consolidator Removal
            if platform.system() == "Windows":
                cmd = '"' + pypath + '" "' + conpath + '" ' + server + " remove"
                call(cmd, shell=True)
            else:
                cmd = conpath + " " + server + " remove"
                call(cmd, shell=True)

            #Alert Manager Removal
            if platform.system() == "Windows":
                cmd = '"' + pypath + '" "' + alarmpath + '" ' + server + " remove"
                call(cmd, shell=True)
            else:
                cmd = conpath + " " + server + " remove"
                call(cmd, shell=True)

        print("Reading Previous Installations From " + storagepath)

        try:
            file = open(storagepath, "r")

            for line in file:
                if str(line) not in drivers:
                    parts = line.split(':')
                    if len(parts) > 1:
                        drivers.append((parts[0],parts[1].strip()))
                        print("Removing Previously Installed Driver: " + str(parts[0]) + " (" + str(parts[1]).strip() + ")")

            file.close()
        except:
            pass
        
        for drv in drivers:
            try:
                if skip == str(drv):
                    continue 
                print("Removing Driver " + str(drv[0]) + "...")
                if platform.system() == "Windows":
                    cmd = pypath + " \"" + basepath + "ardirmdrv.py\" " + str(drv[0]) + " " + server + " --driver " + str(drv[1])
                    if driver != "":
                        cmd += " --ifdriver " + driver
                    print(cmd)
                    call(cmd, shell=True)
                else:
                    cmd = "/opt/ardi/drivers/ardirmdrv " + str(drv[0]) + " " + server
                    if driver != "":
                        cmd += " --ifdriver " + driver
                    call(cmd, shell=True)
            except:
                print('Could Not Remove Driver')

        print("Removal Complete")

    if (mode == 'install'):        
        
        if startcon == True:
            #Consolidator Installation
            if platform.system() == "Windows":
                cmd = '"' + pypath + '" "' + conpath + '" ' + server + ' remove'
                call(cmd, shell=True)

                cmd = '"' + pypath + '" "' + conpath + '" ' + server + " install"
                call(cmd, shell=True)
            else:
                cmd = conpath + " " + server + " remove"
                call(cmd, shell=True)
                
                cmd = conpath + " " + server + " install"
                call(cmd, shell=True)

            #Alert Manager Installation
            if platform.system() == "Windows":
                cmd = '"' + pypath + '" "' + alarmpath + '" ' + server + ' remove'
                call(cmd, shell=True)

                cmd = '"' + pypath + '" "' + alarmpath + '" ' + server + " install"
                call(cmd, shell=True)
            else:
                cmd = alarmpath + " " + server + " remove"
                call(cmd, shell=True)
                
                cmd = alarmpath + " " + server + " install"
                call(cmd, shell=True)

        for drv in drivers:
            try:
                if skip == str(drv[0]):
                    continue
                print("Adding Driver " + str(drv[0]) + "...")
                if platform.system() == "Windows":
                    cmd = pypath + " \"" + basepath + "ardiinstdrv.py\" " + str(drv[0]) + " " + server
                    if driver != "":
                        cmd += " --ifdriver " + driver
                    print(cmd)
                    call(cmd, shell=True)
                else:
                    cmd = "/opt/ardi/drivers/ardiinstdrv " + str(drv[0]) + " " + server
                    if driver != "":
                        cmd += " --ifdriver " + driver
                    call(cmd, shell=True)
            except:
                print('Could Not Add Driver')
        
        file = open(storagepath, "w")

        for n in drivers:
            file.write(str(n[0]) + ":" + str(n[1]) + "\n")

        file.close()        

        print("Recorded Details In " + storagepath)
        
        print("Installation Complete")
