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

import argparse, difflib, json, sys, os, time
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/pdu-python-api")
from raritan.rpc import Agent, Time
from raritan.rpc.smartlock import DoorAccessControl
from raritan.rpc.peripheral import DeviceManager

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

parser = argparse.ArgumentParser(description='Add door access rules to device.')
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)

# Adjust these example rules according to your setup. Note especially:
#
# - doorHandleLocks (should contain "Door Lock" peripheral device slots)
# - cardReader.position (should match position of the needed cardreader)
# - keypad.position (should match position of the needed keypad)
#
# You can use 'print-door-access-setup.py' to view smartlock peripheral devices
# and the current door access rules setup.

# A rule with 1 card and absolute / periodic time conditions
exampleRule1 = DoorAccessControl.DoorAccessRule(
    name = "Access Rule 1",

    # assuming this has a DOOR_HANDLE_LOCK device, check e.g. with print-door-access-setup.py
    doorHandleLocks = [ devMgr.getDeviceSlot(4) ],

    cardCondition1 = DoorAccessControl.CardCondition(
        enabled = True,
        cardUid = "A0001",
        cardReader = DoorAccessControl.CardReaderInfo(
            linkId = 1,
            # assuming a cardreader with this position exists
            position = "D1:C1-0"
        )
    ),

    absoluteTime = DoorAccessControl.AbsoluteTimeCondition(
        enabled = True,
        validFrom = Time.decode(int(time.time())),               # allow from now
        validTill = Time.decode(int(time.time()) + 14*24*60*60)  # until 2 weeks later
    ),

    periodicTime = DoorAccessControl.PeriodicTimeCondition(
        enabled = True,
        daysOfWeek = [2, 3, 4], # allow on Tuesdays, Wednesdays, Thursdays
        fromHourOfDay = 6,      # from 06:00
        fromMinuteOfHour = 0,
        tillHourOfDay = 18,     # till 18:00
        tillMinuteOfHour = 0
    ),

    # just feed the disabled conditions with empty values
    cardCondition2 = DoorAccessControl.CardCondition(False, "", DoorAccessControl.CardReaderInfo(0, "")),
    keypadCondition1 = DoorAccessControl.KeypadCondition(False, "", DoorAccessControl.KeypadInfo(0, "")),
    keypadCondition2 = DoorAccessControl.KeypadCondition(False, "", DoorAccessControl.KeypadInfo(0, "")),

    # not actually used since we only have one auth factor
    conditionsTimeout = 0,
)

# A 2FA rule, needing 1 card and 1 PIN
exampleRule2 = DoorAccessControl.DoorAccessRule(
    name = "Access Rule 2 - 2FA",

    # assuming this has a DOOR_HANDLE_LOCK device, check e.g. with print-door-access-setup.py
    doorHandleLocks = [ devMgr.getDeviceSlot(7) ],

    cardCondition1 = DoorAccessControl.CardCondition(
        enabled = True,
        cardUid = "B0002",
        cardReader = DoorAccessControl.CardReaderInfo(
            linkId = 1,
            # assuming a cardreader with this position exists
            position = "D1:C1-1"
        )
    ),
    keypadCondition1 = DoorAccessControl.KeypadCondition(
        enabled = True,
        pin = "12345",
        keypad = DoorAccessControl.KeypadInfo(
            linkId = 1,
            # assuming a keypad with this position exists
            position = "D1:C1-1"
        )
    ),

    # 10 seconds time before auth factors timeout
    conditionsTimeout = 10,

    # just feed the disabled conditions with empty values
    cardCondition2 = DoorAccessControl.CardCondition(False, "", DoorAccessControl.CardReaderInfo(0, "")),
    keypadCondition2 = DoorAccessControl.KeypadCondition(False, "", DoorAccessControl.KeypadInfo(0, "")),

    absoluteTime = DoorAccessControl.AbsoluteTimeCondition(False, Time.decode(0), Time.decode(0)),
    periodicTime = DoorAccessControl.PeriodicTimeCondition(False, [], 0, 0, 0, 0)

)

doorAccess = DoorAccessControl("/dooraccesscontrol", agent)
doorAccess.addDoorAccessRule(exampleRule1)
doorAccess.addDoorAccessRule(exampleRule2)
