"""MQPCF structures: CFH, CFIN, CFIN64 etc"""

# Copyright (c) 2025 IBM Corporation and other Contributors. All Rights Reserved.
# Copyright (c) 2009-2024 Dariusz Suchojad. All Rights Reserved.

from mqcommon import *
from mqopts import MQOpts
from ibmmq import CMQC, CMQCFC

try:
    from typing import Any, Dict, Union
except ImportError:
    pass

class CFH(MQOpts):
    """ Construct an MQCFH Structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """
    def __init__(self, **kw: Dict[str, Any]):
        opts = [['Type', CMQCFC.MQCFT_COMMAND, MQLONG_TYPE],
                ['StrucLength', CMQCFC.MQCFH_STRUC_LENGTH, MQLONG_TYPE],
                ['Version', CMQCFC.MQCFH_VERSION_3, MQLONG_TYPE],
                ['Command', CMQCFC.MQCMD_NONE, MQLONG_TYPE],
                ['MsgSeqNumber', 1, MQLONG_TYPE],
                ['Control', CMQCFC.MQCFC_LAST, MQLONG_TYPE],
                ['CompCode', CMQC.MQCC_OK, MQLONG_TYPE],
                ['Reason', CMQC.MQRC_NONE, MQLONG_TYPE],
                ['ParameterCount', 0, MQLONG_TYPE],
                ]

        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFBF(MQOpts):
    """ Construct an MQCFBF (PCF Byte String Filter) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """

    def __init__(self, **kw: Dict[str, Any]):
        filter_value = kw.pop('FilterValue', '')
        filter_value_length = kw.pop('FilterValueLength', len(filter_value))  # type: int
        padded_filter_value_length = padded_count(filter_value_length)

        opts = [['Type', CMQCFC.MQCFT_BYTE_STRING_FILTER, MQLONG_TYPE],
                ['StrucLength',
                 CMQCFC.MQCFBF_STRUC_LENGTH_FIXED + padded_filter_value_length, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['Operator', 0, MQLONG_TYPE],
                ['FilterValueLength', filter_value_length, MQLONG_TYPE],
                ['FilterValue', filter_value, '{}s'.format(padded_filter_value_length)]
                ]

        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFBS(MQOpts):
    """ Construct an MQCFBS (PCF Byte String) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """

    def __init__(self, **kw: Dict[str, Any]):
        string = kw.pop('String', '')
        string_length = kw.pop('StringLength', len(string))  # type: int
        padded_string_length = padded_count(string_length)

        opts = [['Type', CMQCFC.MQCFT_BYTE_STRING, MQLONG_TYPE],
                ['StrucLength', CMQCFC.MQCFBS_STRUC_LENGTH_FIXED + padded_string_length, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['StringLength', string_length, MQLONG_TYPE],
                ['String', string, '{}s'.format(padded_string_length)]
                ]

        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFGR(MQOpts):
    """ Construct an MQCFGR (PCF Group) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """

    def __init__(self, **kw: Dict[str, Any]):
        count = kw.pop('ParameterCount', 0)

        opts = [['Type', CMQCFC.MQCFT_GROUP, MQLONG_TYPE],
                ['StrucLength', CMQCFC.MQCFGR_STRUC_LENGTH, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['ParameterCount', count, MQLONG_TYPE],
                ]
        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFIF(MQOpts):
    """ Construct an MQCFIF (PCF Integer Filter) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """

    def __init__(self, **kw: Dict[str, Any]):
        opts = [['Type', CMQCFC.MQCFT_INTEGER_FILTER, MQLONG_TYPE],
                ['StrucLength', CMQCFC.MQCFIF_STRUC_LENGTH, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['Operator', 0, MQLONG_TYPE],
                ['FilterValue', 0, MQLONG_TYPE]
                ]

        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFIL(MQOpts):
    """ Construct an MQCFIL (PCF 32-bit integer List) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """
    def __init__(self, **kw: Dict[str, Any]):
        values = kw.pop('Values', [])  # type: list[int]
        count = kw.pop('Count', len(values))  # type: int

        opts = [['Type', CMQCFC.MQCFT_INTEGER_LIST, MQLONG_TYPE],
                ['StrucLength', CMQCFC.MQCFIL_STRUC_LENGTH_FIXED + 4 * count, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['Count', count, MQLONG_TYPE],
                ['Values', values, MQLONG_TYPE, count],
                ]
        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFIL64(MQOpts):
    """ Construct an MQCFIL64 (PCF 64-bit integer List) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """
    def __init__(self, **kw: Dict[str, Any]):
        values = kw.pop('Values', [])  # type: list[int]
        count = kw.pop('Count', len(values))  # type: int

        opts = [['Type', CMQCFC.MQCFT_INTEGER64_LIST, MQLONG_TYPE],
                ['StrucLength', CMQCFC.MQCFIL64_STRUC_LENGTH_FIXED + 8 * count, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['Count', count, MQLONG_TYPE],
                ['Values', values, INTEGER64_TYPE, count],
                ]
        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFIN(MQOpts):
    """ Construct an MQCFIN (PCF 32-bit integer) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """
    def __init__(self, **kw: Dict[str, Any]):
        opts = [['Type', CMQCFC.MQCFT_INTEGER, MQLONG_TYPE],
                ['StrucLength', CMQCFC.MQCFIN_STRUC_LENGTH, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['Value', 0, MQLONG_TYPE],
                ]
        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFIN64(MQOpts):
    """ Construct an MQCFIN64 (PCF 64-bit integer) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """
    def __init__(self, **kw: Dict[str, Any]):
        opts = [['Type', CMQCFC.MQCFT_INTEGER64, MQLONG_TYPE],
                ['StrucLength', CMQCFC.MQCFIN64_STRUC_LENGTH, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['Value', 0, INTEGER64_TYPE],
                ]
        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFSF(MQOpts):
    """ Construct an MQCFSF (PCF String Filter) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """

    def __init__(self, **kw: Dict[str, Any]):
        filter_value = kw.pop('FilterValue', '')
        filter_value_length = kw.pop('FilterValueLength', len(filter_value))  # type: int
        padded_filter_value_length = padded_count(filter_value_length)

        opts = [['Type', CMQCFC.MQCFT_STRING_FILTER, MQLONG_TYPE],
                ['StrucLength',
                 CMQCFC.MQCFSF_STRUC_LENGTH_FIXED + padded_filter_value_length, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['Operator', 0, MQLONG_TYPE],
                ['CodedCharSetId', CMQC.MQCCSI_DEFAULT, MQLONG_TYPE],
                ['FilterValueLength', filter_value_length, MQLONG_TYPE],
                ['FilterValue', filter_value, '{}s'.format(padded_filter_value_length)]
                ]

        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFSL(MQOpts):
    """ Construct an MQCFSL (PCF String List) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    """

    def __init__(self, **kw: Dict[str, Any]):
        strings = kw.pop('Strings', [])  # type: list[Union[str,bytes]]
        string_length = kw.pop('StringLength', len(max(strings, key=len)) if strings else 0)  # type: int

        strings_count = len(strings)
        count = kw.pop('Count', strings_count)  # type: int

        max_string_length = padded_count(string_length) if count else 0
        padded_strings_length = (max_string_length) * strings_count

        opts = [['Type', CMQCFC.MQCFT_STRING_LIST, MQLONG_TYPE],
                ['StrucLength', CMQCFC.MQCFSL_STRUC_LENGTH_FIXED + padded_strings_length, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['CodedCharSetId', CMQC.MQCCSI_DEFAULT, MQLONG_TYPE],
                ['Count', count, MQLONG_TYPE],
                ['StringLength', max_string_length, MQLONG_TYPE],
                ['Strings', strings if strings else [b''], '{}s'.format(max_string_length), (count if count else 1)]
                ]

        super().__init__(tuple(opts), **kw)

# ################################################################################################################################

class CFST(MQOpts):
    """ Construct an MQCFST (PCF String) structure with default values as per MQI.
    The default values may be overridden by the optional keyword arguments 'kw'.
    Note that the "String" may include the padding bytes, so you have to use the
    StringLength field to extract the real value.
    """

    def __init__(self, **kw: Dict[str, Any]):
        string = kw.pop('String', '')
        string_length = kw.pop('StringLength', len(string))  # type: int
        padded_string_length = padded_count(string_length)

        opts = [['Type', CMQCFC.MQCFT_STRING, MQLONG_TYPE],
                ['StrucLength', CMQCFC.MQCFST_STRUC_LENGTH_FIXED + padded_string_length, MQLONG_TYPE],
                ['Parameter', 0, MQLONG_TYPE],
                ['CodedCharSetId', CMQC.MQCCSI_DEFAULT, MQLONG_TYPE],
                ['StringLength', string_length, MQLONG_TYPE],
                ['String', string, '{}s'.format(padded_string_length)]
                ]

        super().__init__(tuple(opts), **kw)
