#!/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 os
import sys

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


class VOSGroup(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_group")
        self.rpcQueue = params["rpc_queue"]
        super(VOSGroup, self).__init__(self.host, self.port, self.db, self.rpcQueue)

    def addGroup(self, groupType, groupname, vospacePath):
        vospacePath = vospacePath.rstrip('/')
        if groupType == "read":
            requestType = "GRPR_ADD"
        else:
            requestType = "GRPW_ADD"
        addGroupRequest = { "requestType": requestType, "vospacePath": vospacePath, "groupName": groupname }
        addGroupResponse = self.call(addGroupRequest)
        if "responseType" not in addGroupResponse:
            sys.exit("FATAL: Malformed response, storage acknowledge expected.\n")
        elif addGroupResponse["responseType"] == "GRPR_STARTED":
            print("\nThe procedure that adds the group to 'group_read' has started.")
            print("If notifications are enabled, you will receive an email as soon as the job is completed.\n")
        elif addGroupResponse["responseType"] == "GRPW_STARTED":
            print("\nThe procedure that adds the group to 'group_write' has started.")
            print("If notifications are enabled, you will receive an email as soon as the job is completed.\n")
        elif addGroupResponse["responseType"] == "ERROR":
            errorCode = addGroupResponse["errorCode"]
            errorMsg = addGroupResponse["errorMsg"]
            sys.exit(f"\nError code: {errorCode}\nError message: {errorMsg}\n")
        else:
            sys.exit("\nFATAL: Unknown response type.\n")

    def delGroup(self, groupType, groupname, vospacePath):
        vospacePath = vospacePath.rstrip('/')
        if groupType == "read":
            requestType = "GRPR_DEL"
        else:
            requestType = "GRPW_DEL"
        delGroupRequest = { "requestType": requestType, "vospacePath": vospacePath, "groupName": groupname }
        delGroupResponse = self.call(delGroupRequest)
        if "responseType" not in delGroupResponse:
            sys.exit("FATAL: Malformed response.\n")
        elif delGroupResponse["responseType"] == "GRPR_STARTED":
            print("\nThe procedure that removes the group from 'group_read' has started.")
            print("If notifications are enabled, you will receive an email as soon as the job is completed.\n")
        elif delGroupResponse["responseType"] == "GRPW_STARTED":
            print("\nThe procedure that removes the group from 'group_write' has started.")
            print("If notifications are enabled, you will receive an email as soon as the job is completed.\n")
        elif delGroupResponse["responseType"] == "ERROR":
            errorCode = delGroupResponse["errorCode"]
            errorMsg = delGroupResponse["errorMsg"]
            sys.exit(f"\nError code: {errorCode}\nError message: {errorMsg}\n")
        else:
            sys.exit("\nFATAL: Unknown response type.\n")
            
    def listGroups(self, groupType, vospacePath):
        vospacePath = vospacePath.rstrip('/')
        if groupType == "read":
            requestType = "GRPR_LST"
        else:
            requestType = "GRPW_LST"
        listGroupsRequest = { "requestType": requestType, "vospacePath": vospacePath }
        listGroupsResponse = self.call(listGroupsRequest)
        if "responseType" not in listGroupsResponse:
            sys.exit("FATAL: Malformed response.\n")
        elif listGroupsResponse["responseType"] == "GRPR_LST_DONE" or listGroupsResponse["responseType"] == "GRPW_LST_DONE":
            groupList = listGroupsResponse["groupList"]
            if not groupList:
                sys.exit(f"\n'group_{groupType}' is empty.\n")
            print()
            print(tabulate(groupList, headers = "keys", tablefmt = "pretty"))
            print()
        elif listGroupsResponse["responseType"] == "ERROR":
            errorCode = listGroupsResponse["errorCode"]
            errorMsg = listGroupsResponse["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_group

SYNOPSYS
       vos_group GROUP_TYPE METHOD [GROUP_NAME] VOSPACE_PATH

DESCRIPTION
       This tool allows to modify 'group_read' and 'group_write'
       parameters of a VOSpace node.

       Four parameters are required:

       GROUP_TYPE:
           specifies the group type: allowed values are 'read' or 'write'

       METHOD:
           there are three supported methods:
               1. 'add': adds a group to a node
               2. 'del': removes a group from a node
               3. 'list': lists all groups associated to a node

       GROUP_NAME:
           represents a group of users or a single user.
           In the first case, just specify the group name.
           In the second case, the group name syntax is:

               people.name\\\.surname

       VOSPACE_PATH:
           represents the node VOSpace path.

EXAMPLES
      1) Add 'jane.lee' to 'group_read' for the VOSpace node '/john.smith/test/foo' and any child nodes:

      # vos_group read add people.jane\\\.lee /john.smith/test/foo

      2) Add 'my_group' to 'group_write' for the VOSpace node '/john.smith/test/foo' and any child nodes:

      # vos_group write add my_group /john.smith/test/foo
      
      3) Remove 'my_group' from 'group_write' for the VOSpace node '/john.smith/test/foo' and any child nodes:

      # vos_group write del my_group /john.smith/test/foo
      
      4) List all groups in 'group_read' for the VOSpace node '/john.smith/test/foo':

      # vos_group read list /john.smith/test/foo
    """)

# Create new VOSChcrt object
vosGroupCli = VOSGroup()

# Check the number of input args
if len(sys.argv) == 5:
    script, groupType, method, groupname, vospacePath = sys.argv
elif len(sys.argv) == 4:
    script, groupType, method, vospacePath = sys.argv
else:
    vosGroupCli.help()

if groupType != "read" and groupType != "write":
    vosGroupCli.help()

if method == "add":
    vosGroupCli.addGroup(groupType, groupname, vospacePath)
elif method == "del":
    vosGroupCli.delGroup(groupType, groupname, vospacePath)
elif method == "list":
    vosGroupCli.listGroups(groupType, vospacePath)
else:
    vosGroupCli.help()
