#!/usr/bin/python3
# SPDX-License-Identifier: BSD-3-Clause
#
# Copyright 2022 Raritan Inc. All rights reserved.

import argparse, difflib, json, sys, os
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/pdu-python-api")
from raritan.rpc import Agent, BulkRequestHelper
from raritan.rpc.smartlock import DoorAccessControl, KeypadManager
from raritan.rpc.smartcard import CardReaderManager
from raritan.rpc.peripheral import DeviceManager
from raritan.rpc.sensors import Sensor

# default values
ip = "10.0.42.2"
user = "admin"
pw = "raritan"

parser = argparse.ArgumentParser(description='List door access rules and smartlock devices.')
parser.add_argument('--ip', dest='ip', action='store', default=ip, help='ip address')
parser.add_argument('--user', dest='user', action='store', default=user, help='user name')
parser.add_argument('--passwd', dest='pw', action='store', default=pw, help='password')
args = parser.parse_args()

agent = Agent("https", args.ip, args.user, args.pw, disable_certificate_verification = True)

devMgr = DeviceManager("/model/peripheraldevicemanager", agent)
slots = devMgr.getDeviceSlots()

# calling getDevice() sequentially on every device slot takes some time, use bulk request
bulk = BulkRequestHelper(agent)
for slot in slots:
    bulk.add_request(slot.getDevice)
slotDevices = bulk.perform_bulk()

print("--- Door Locks: ---")
indexedSlotWithDevice = enumerate(zip(slots, slotDevices))
indexedDoorLockSlotsWithDevice = [(ind, (slot,device)) for ind, (slot, device) in indexedSlotWithDevice
                                  if device != None and device.deviceID.type.type == Sensor.DOOR_HANDLE_LOCK]
if len(indexedDoorLockSlotsWithDevice) > 0:
    for i, (doorLockSlot,device) in indexedDoorLockSlotsWithDevice:
        print(f"Name: {doorLockSlot.getSettings().name}")
        print(f"Device Slot Index: {i}")
        print(f"serial: {device.deviceID.serial}")
        print(f"channel: {device.deviceID.channel}")
        print()
else:
    print("-- none --")
    print()

cardReaderMgr = CardReaderManager("/cardreader", agent)
cardReaders = cardReaderMgr.getCardReaders()
print("--- Card Readers: ---")
if len(cardReaders) > 0:
    for cardReader in cardReaders:
        metaData = cardReader.getMetaData()
        print(f"ID: {metaData.id}")
        print(f"Manufacturer/Product: {metaData.manufacturer}, {metaData.product}")
        print(f"serial/channel: {metaData.serialNumber}, {metaData.channel}")
        print(f"Position: {metaData.position}")
        print()
else:
    print("-- none --")
    print()

keypadMgr = KeypadManager("/keypad", agent)
keypads = keypadMgr.getKeypads()
print("--- Keypads: ---")
if len(keypads) > 0:
    for keypad in keypads:
        metaData = keypad.getMetaData()
        print(f"ID: {metaData.id}")
        print(f"Manufacturer/Product: {metaData.manufacturer}, {metaData.product}")
        print(f"serial/channel: {metaData.serialNumber}, {metaData.channel}")
        print(f"Position: {metaData.position}")
        print()
else:
    print("-- none --")
    print()

doorAccess = DoorAccessControl("/dooraccesscontrol", agent)
rules = doorAccess.getDoorAccessRules()
print("--- Door Access Rules: ---")
if len(rules) > 0:
    for ruleId in rules:
        print(f"Rule {ruleId}:")

        rule = rules[ruleId]
        ruleJson = rule.encode()

        # simplify output: only show enabled conditions:
        if not rule.cardCondition1.enabled:
            del ruleJson['cardCondition1']
        if not rule.cardCondition2.enabled:
            del ruleJson['cardCondition2']
        if not rule.keypadCondition1.enabled:
            del ruleJson['keypadCondition1']
        if not rule.keypadCondition2.enabled:
            del ruleJson['keypadCondition2']

        if not rule.absoluteTime.enabled:
            del ruleJson['absoluteTime']
        if not rule.periodicTime.enabled:
            del ruleJson['periodicTime']

        # only show conditions timeout if we have multiple auth factors:
        conditions = [ rule.cardCondition1, rule.cardCondition2,
                       rule.keypadCondition1, rule.keypadCondition2 ]
        is2FA = sum(cond.enabled for cond in conditions) > 1
        if not is2FA:
            del ruleJson['conditionsTimeout']

        print(json.dumps(ruleJson, indent=4))
        print()
else:
    print("-- none --")
