''' *****************************************************************************
*
* Sentinel LDK Licensing API
*
* Copyright (C) 2024 THALES. All rights reserved.
*
***************************************************************************** '''

import ctypes
import hasp_constants
import platform
import sys

if sys.platform.startswith('win32'):
    hasp_dll = ctypes.WinDLL("./hasp_windows_x64_demo.dll")
elif sys.platform.startswith('linux'):
    hasp_dll = ctypes.CDLL("./libhasp_linux_x86_64_demo.so")
elif sys.platform.startswith('darwin'):
    hasp_dll = ctypes.CDLL("./hasp_darwin_demo.dylib")

'''------------------------------------------------------------------------------
The Basic API
------------------------------------------------------------------------------'''
def hasp_get_version(vendor_code ,version) -> hasp_constants.hasp_status_t:
    int_major_ver = ctypes.c_int(0)
    int_minor_ver = ctypes.c_int(0) 
    int_build_server = ctypes.c_int(0)
    int_build_number = ctypes.c_int(0)
    status = hasp_dll.hasp_get_version(ctypes.byref(int_major_ver),
                                       ctypes.byref(int_minor_ver),
                                       ctypes.byref(int_build_server),
                                       ctypes.byref(int_build_number),
                                       vendor_code.encode())
    # dotted string version
    version.append(str(int_major_ver.value) + '.' +
                   str(int_minor_ver.value) + '.' +
                   str(int_build_server.value) + '.' +
                   str(int_build_number.value)) 
    return status

def hasp_login(feature, vendor_code, handle) -> hasp_constants.hasp_status_t:
    hasp_handle = ctypes.c_int(0)
    status = hasp_dll.hasp_login(feature,
                                 vendor_code.encode(),
                                 ctypes.byref(hasp_handle))
    handle.append(hasp_handle.value)
    return status

def hasp_login_scope(feature, scope, vendor_code, handle) -> hasp_constants.hasp_status_t:
    hasp_handle = ctypes.c_int(0)
    status = hasp_dll.hasp_login_scope(feature,
                                       scope.encode(),
                                       vendor_code.encode(),
                                       ctypes.byref(hasp_handle))
    handle.append(hasp_handle.value)
    return status

def hasp_logout(handle) -> hasp_constants.hasp_status_t:
    status = hasp_dll.hasp_logout(handle[0])
    return status

def hasp_get_size(handle,fileid,mem_size) -> hasp_constants.hasp_status_t:
    memory_size = ctypes.c_int(0)
    status = hasp_dll.hasp_get_size(handle[0],
                                    fileid,
                                    ctypes.byref(memory_size))
    mem_size.append(memory_size.value)
    return status

def hasp_read(handle,fileid,offset, len, data) -> hasp_constants.hasp_status_t: 
    status = hasp_dll.hasp_read(handle[0],
                                fileid,
                                offset,
                                len,
                                data)
    return status

def hasp_write(handle,fileid,offset, len, data) -> hasp_constants.hasp_status_t:
    status = hasp_dll.hasp_write(handle[0],
                                 fileid,
                                 offset,
                                 len,
                                 data)
    return status

def hasp_get_rtc(handle,time) -> hasp_constants.hasp_status_t:
    ltime = ctypes.c_int( 0 )
    status = hasp_dll.hasp_get_rtc(handle[0],
                                   ctypes.byref(ltime))
    time.append(ltime.value)
    return status

def hasp_get_info(scope, hasp_format, vendor_code, info ) -> hasp_constants.hasp_status_t: 
    pStrData = ctypes.c_char_p( )
    status = hasp_dll.hasp_get_info(scope.encode(),
                                    hasp_format.encode(),
                                    vendor_code.encode(),
                                    ctypes.byref (pStrData ))
    info.append(pStrData)
    return status

def hasp_get_sessioninfo(handle, format,info ) -> hasp_constants.hasp_status_t:
    pStrData = ctypes.c_char_p ()
    status = hasp_dll.hasp_get_sessioninfo(handle[0],
                                           format.encode(),
                                           ctypes.byref (pStrData ))
    info.append(pStrData)
    return status

def hasp_encrypt(handle, data, len ) -> hasp_constants.hasp_status_t: 
    status = hasp_dll.hasp_encrypt(handle[0],
                                   data,
                                   len)
    return status

def hasp_decrypt(handle, data, len ) -> hasp_constants.hasp_status_t: 
    status = hasp_dll.hasp_decrypt(handle[0],
                                   data,
                                   len)
    return status

def hasp_free(info) -> hasp_constants.hasp_status_t:
    status = hasp_dll.hasp_free(info)
    return status

def hasp_hasptime_to_datetime(time, day, month, year, hour, minute, second) -> hasp_constants.hasp_status_t:
    lday = ctypes.c_int( 0 )
    lmonth = ctypes.c_int( 0 )
    lyear = ctypes.c_int( 0 )
    lhour = ctypes.c_int( 0 )
    lminute = ctypes.c_int( 0 )
    lsecond = ctypes.c_int( 0 )
    status = hasp_dll.hasp_hasptime_to_datetime(time,
                                                ctypes.byref(lday),
                                                ctypes.byref(lmonth),
                                                ctypes.byref(lyear),
                                                ctypes.byref(lhour),
                                                ctypes.byref(lminute),
                                                ctypes.byref(lsecond))
    day.append(lday.value)
    month.append(lmonth.value)
    year.append(lyear.value)
    hour.append(lhour.value)
    minute.append(lminute.value)
    second.append(lsecond.value)
    return status

def hasp_update(update, ack)-> hasp_constants.hasp_status_t:
    pStrData = ctypes.c_char_p( )
    status = hasp_dll.hasp_update(update.encode(),
                                  ctypes.byref (pStrData ))
    ack.append(pStrData)
    return status


def hasp_transfer(action, scope, vendor_code, recipient,output)-> hasp_constants.hasp_status_t:
    pStrData = ctypes.c_char_p( )
    status = hasp_dll.hasp_transfer(action.encode(),
                               scope.encode(),
                               vendor_code.encode(),
                               recipient,
                               ctypes.byref (pStrData ))
    output.append(pStrData)
    return status
