#!/usr/bin/env python
#
# This file is part of vospace-transfer-service
# Copyright (C) 2021 Istituto Nazionale di Astrofisica
# SPDX-License-Identifier: GPL-3.0-or-later
#

import sys

from redis_rpc_client import RedisRPCClient
from config import Config
from tabulate import tabulate


class VOSData(RedisRPCClient):

    def __init__(self):
        config = Config("/etc/vos_cli/vos_cli.conf")
        params = config.loadSection("server")
        self.host = params["host"]
        self.port = params.getint("port")
        self.db = params.getint("db")
        params = config.loadSection("vos_data")
        self.rpcQueue = params["rpc_queue"]
        super(VOSData, self).__init__(self.host, self.port, self.db, self.rpcQueue)

    def help(self):
        sys.exit("""
NAME
       vos_data

SYNOPSYS
       vos_data COMMAND USERNAME

DESCRIPTION
       The purpose of this client application is to notify to the VOSpace backend that
       data is ready to be saved somewhere.

       The client accepts only one (mandatory) command at a time.
       A list of supported commands is shown here below:

       cstore
              performs a 'cold storage' request, data will be saved on tape

       hstore
              performs a 'hot storage' request, data will be saved to disk

       The client also needs to know the username associated to a storage request process.
       The username must be the same used for accessing the transfer node.

EXAMPLES
      1) Perform a hot storage request for the data contained in the 'store path' associated 
      to the user 'john.smith':
      
      # vos_data hstore john.smith

      2) Perform a cold storage request for the data contained in the 'store path' associated 
      to the user 'john.smith':
      
      # vos_data cstore john.smith

      The 'store path' parameter is defined in the 'storage section' of the transfer service
      main configuration file: '/etc/vos_ts/vos_ts.conf'.
    """)

    def store(self, cmd, username):
        request_type = cmd.upper()
        storeRequest = { "requestType": request_type, "userName": username }
        print(f"\nSending {request_type} request...\n")
        storeResponse = self.call(storeRequest)
        if "responseType" not in storeResponse:
            sys.exit("FATAL: Malformed response, storage acknowledge expected.\n")
        elif storeResponse["responseType"] == "STORE_ACK":
            storageList = storeResponse["storageList"]
            storageType = storageList[0]["storage_type"]
            if not storageList:
                sys.exit("No storage point found. Please add a storage point using the 'vos_storage' command.\n")
            print("Choose one of the following storage locations:")
            print("\n" + tabulate(storageList, headers = "keys", tablefmt = "pretty") + "\n")
            storageIdList = []
            for st in storageList:
                storageIdList.append(st["storage_id"])
            storageId = None
            while storageId not 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("\n!!!!!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
            print("! If you confirm, all your data on the transfer node will be !")
            print("! available in read-only mode for all the time the storage   !")
            print("! process is running.                                        !")
            print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n")
            confirm = None
            while confirm not 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": "STORE_CON", 
                                   "userName": username, 
                                   "storageId": storageId, 
                                   "storageType": storageType }
                confirmResponse = self.call(confirmRequest)
                if "responseType" not in confirmResponse:
                    sys.exit("\nFATAL: Malformed response, storage confirmation expected.\n")
                elif confirmResponse["responseType"] == "STORE_RUN":
                    jobId = confirmResponse["jobId"]
                    print(f"\nJobID: {jobId}")
                    print("Storage process started 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("FATAL: Unknown response type.\n")
            else:
                sys.exit("\nStorage process aborted gracefully.\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")


# Create new VOSData object
vosDataCli = VOSData()

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

# Check the command passed by the user
if cmd == "cstore" or cmd == "hstore":
    vosDataCli.store(cmd, username)
else:
    vosDataCli.help()
