# standard library
import logging
import base64
import hashlib
import json
from Cryptodome.Cipher import AES  # pip install pycryptodomex


class SvCipherOpenSsl:
    """
    compatible with php openssl_encrypt()
    this class can be utilzied between python-php secured communcation
    refer to https://github.com/arajapandi/php-python-encrypt-decrypt
    """
    # rawkey = 'asdfa923aksadsYahoasdw998sdsads'
    method = AES.MODE_CFB
    blocksize = 32  # 16, 32..etc
    padwith = '`'  # padding value for string
    __g_oLogger = None
    iv = None
    key = None

    def __init__(self):
        self.__g_oLogger = logging.getLogger(__file__)

    # lambda function for padding
    def pad(self, s):
        return s + (self.blocksize - len(s) % self.blocksize) * bytes(self.padwith, 'utf-8')

    def set_iv(self, sIv):
        self.iv = sIv

    def set_secret_key(self, sSecretKey):
        self.key = sSecretKey

    def encrypt_string(self, raw):
        """Encrypt given string using AES encryption standard"""
        raw = json.dumps(raw)
        cipher = AES.new(self.__get_key(), self.method, self.__get_iv(), segment_size=128)
        return base64.b64encode(cipher.encrypt(self.pad(raw.encode('utf8'))))

    def decrypt_string(self, encrypted):
        """Decrypt given string using AES standard"""
        encrypted = base64.b64decode(encrypted)
        cipher = AES.new(self.__get_key(), self.method, self.__get_iv(), segment_size=128)
        return cipher.decrypt(encrypted).decode('utf-8').rstrip(self.padwith)

    def translate_msg_code(self, s_encrypted):
        if not s_encrypted:
            return
        s_decrypted = self.decrypt_string(s_encrypted)
        return json.loads(s_decrypted)

    def __get_key(self):
        """get hashed key - if key is not set on init, then default key wil be used"""
        if not self.key:
            self.__printDebug('hashed key not exists')
            return False
        else:
            # print(self.key)
            return bytes(hashlib.sha256(self.key.encode('utf-8')).hexdigest()[:32], 'utf-8')

    def __get_iv(self):
        """ get hashed IV value - if no IV values then it throw error"""
        if not self.iv:
            self.__printDebug('hashed IV not exists')
            return False
        else:
            return bytes(hashlib.sha256(self.iv.encode('utf-8')).hexdigest()[:16], 'utf-8')


if __name__ == '__main__':  # for console debugging
    secret = b'TestString From PHP345'
    print(secret)
    sv_secret_key = '34yuhangencer4ty'
    sv_iv = 'HyuhangenDdfe5gh'

    oSvCipher = SvCipherOpenSsl()
    oSvCipher.set_iv(sv_iv)
    oSvCipher.set_secret_key(sv_secret_key)

    s_enc = oSvCipher.encrypt_string(secret).decode("utf-8")
    print(s_enc)

    print(oSvCipher.decrypt_string(s_enc.encode("utf-8")))
#    oSvCipher = svCipher()
#    sv_secret_key = '34yuhanroxc13234'
#    sv_iv = 'HyuhanroxD567856'
#    oSvCipher.setIv(sv_iv)
#    oSvCipher.setSecretKey(sv_secret_key)
#
#    enc_text = oSvCipher.encryptString('test message')
#    print(enc_text)
#    dec_text = oSvCipher.decryptString(enc_text)
#    print(dec_text)
