#!/usr/bin/env python

import sys

from amqp_client import AMQPClient
from config import Config
from tabulate import tabulate


class VOSStorage(AMQPClient):
  
    def __init__(self):
        config = Config("/etc/vos_cli/vos_cli.conf")
        self.params = config.loadSection("server")
        self.host = self.params["host"]
        self.port = self.params.getint("port")
        self.params = config.loadSection("vos_storage")
        self.rpcQueue = self.params["rpc_queue"]
        super(VOSStorage, self).__init__(self.host, self.port, self.rpcQueue)

    def add(self):
        storageType = None
        storageBasePath = None
        storageBaseUrl = None
        storageHostname = None
        while not storageType in ("cold", "hot", "portal"):
                try:
                    storageType = input("\nStorage type [cold, hot or portal]: ")
                except ValueError:
                    print("Input type is not valid!")
                except EOFError:
                    print("\nPlease, use CTRL+C to quit.")
                except KeyboardInterrupt:
                    sys.exit("\nCTRL+C detected. Exiting...")
        while not (storageBasePath or storageBaseUrl):
            try:
                if storageType == "portal":
                    storageBaseUrl = input("\nStorage base url: ")
                else:
                    storageBasePath = input("\nStorage base path: ")
            except ValueError:
                print("Input type is not valid!")
            except EOFError:
                print("\nPlease, use CTRL+C to quit.")
            except KeyboardInterrupt:
                sys.exit("\nCTRL+C detected. Exiting...")
        while not storageHostname:
            try:
                storageHostname = input("\nStorage hostname: ")
            except ValueError:
                print("Input type is not valid!")
            except EOFError:
                print("\nPlease, use CTRL+C to quit.")
            except KeyboardInterrupt:
                sys.exit("\nCTRL+C detected. Exiting...")
        storageRequest = { "requestType": "STORAGE_ADD", 
                           "storageType": storageType, 
                           "basePath": storageBasePath,
                           "baseUrl": storageBaseUrl,
                           "hostname": storageHostname }
        storageResponse = self.call(storageRequest)
        
        if "responseType" not in storageResponse:
            sys.exit("FATAL: Malformed response, storage acknowledge expected.\n")
        elif storageResponse["responseType"] == "STORAGE_ADD_DONE":
            print("\nStorage point added successfully!\n")
        elif storageResponse["responseType"] == "ERROR":
            errorCode = storageResponse["errorCode"]
            errorMsg = storageResponse["errorMsg"]
            sys.exit(f"\nError code: {errorCode}\nError message: {errorMsg}\n")
        else:
            sys.exit("\nFATAL: Unknown response type.\n")

    def delete(self):
        storageRequest = { "requestType": "STORAGE_DEL_REQ" }
        storageResponse = self.call(storageRequest)
        
        if "responseType" not in storageResponse:
            sys.exit("FATAL: Malformed response, storage acknowledge expected.\n")
        elif storageResponse["responseType"] == "STORAGE_DEL_ACK":
            storageList = storageResponse["storageList"]
            if not storageList:
                sys.exit("No storage point found. Please add at least one storage point.\n")
            print("\nSelect the storage location to remove:\n")
            print(tabulate(storageList, headers = "keys", tablefmt = "pretty"))
            print()
            storageIdList = []
            for st in storageList:
                storageIdList.append(st["storage_id"])
            storageId = None
            while not storageId in storageIdList:
                try:
                    storageId = input("Please, insert a storage id: ")
                    storageId = int(storageId)
                except ValueError:
                    print("Input type is not valid!")
                except EOFError:
                    print("\nPlease, use CTRL+C to quit.")
                except KeyboardInterrupt:
                    sys.exit("\nCTRL+C detected. Exiting...")
            print()
            print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
            print("! This operation will remove the selected storage location only !")
            print("! from the database.                                            !")
            print("! The mount point on the transfer node will not be removed, you !")
            print("! must do it manually.                                          !")
            print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
            print()
            confirm = None
            while not confirm in ( "yes", "no" ):
                try:
                    confirm = input("Are you sure to proceed? [yes/no]: ")
                except KeyboardInterrupt:
                    sys.exit("\nCTRL+C detected. Exiting...")
                except EOFError:
                    print("\nPlease, use CTRL+C to quit.")
            if confirm == "yes":
                confirmRequest = { "requestType": "STORAGE_DEL_CON", "storageId": storageId }
                confirmResponse = self.call(confirmRequest)
                if "responseType" not in confirmResponse:
                    sys.exit("\nFATAL: Malformed response, storage confirmation expected.\n")
                elif confirmResponse["responseType"] == "STORAGE_DEL_DONE":
                    print("\nStorage location deleted successfully!\n")
                elif confirmResponse["responseType"] == "ERROR":
                    errorCode = confirmResponse["errorCode"]
                    errorMsg = confirmResponse["errorMsg"]
                    sys.exit(f"\nError code: {errorCode}\nError message: {errorMsg}\n")
                else:
                    sys.exit("\nFATAL: Unknown response type.\n")
        elif storeResponse["responseType"] == "ERROR":
            errorCode = storeResponse["errorCode"]
            errorMsg = storeResponse["errorMsg"]
            sys.exit(f"Error code: {errorCode}\nError message: {errorMsg}\n")
        else:
            sys.exit("\nFATAL: Unknown response type.\n")
            
    def list(self):
        storageRequest = { "requestType": "STORAGE_LST" }
        storageResponse = self.call(storageRequest)
        
        if "responseType" not in storageResponse:
            sys.exit("FATAL: Malformed response, storage acknowledge expected.\n")
        elif storageResponse["responseType"] == "STORAGE_LST_DONE":
            print()
            print(tabulate(storageResponse["storageList"], headers = "keys", tablefmt = "pretty"))
            print()
        elif storageResponse["responseType"] == "ERROR":
            errorCode = storageResponse["errorCode"]
            errorMsg = storageResponse["errorMsg"]
            sys.exit(f"\nError code: {errorCode}\nError message: {errorMsg}\n")
        else:
            sys.exit("\nFATAL: Unknown response type.\n")
            
    def help(self):
        sys.exit("""
NAME
       vos_storage

SYNOPSYS
       vos_storage COMMAND

DESCRIPTION
       Client tool to manage VOSpace storage points.
       
       The client accepts only one (mandatory) command at a time.
       A list of supported commands is shown here below:

       add
           adds a storage point to the database
       
       del
           deletes a storage point from the database
       
       list
           prints the full storage point list
    """)

# Create new VOSStorage object
vosStorageCli = VOSStorage()

# Check the number of input args
if len(sys.argv) == 2:
    script, cmd = sys.argv
else:
    vosStorageCli.help()

if cmd == "add":
    vosStorageCli.add()
elif cmd == "list":
    vosStorageCli.list()
elif cmd == "del":
    vosStorageCli.delete()
else:
    vosStorageCli.help()
