import os
from pydantic import BaseModel, Field, field_serializer
import tomllib
from enum import Enum
from pathlib import Path


class _ReportStruct(BaseModel):
    """
    Patterns. Use for function get_obj_report. Only for struct. Generate custom struct report instead standart. Where %nxx: n - name of struct element,
    xx - index of struct element; %vxx: v - value of struct element, xx - index of struct element
    """
    DayProfileAction: str = "%n00: %v00 - Тариф: %v02"


class _Report(BaseModel):
    empty: str = "--"
    empty_unit: str = "??"
    scaler_format: str = "{:.3f}"
    struct: _ReportStruct = Field(default_factory=_ReportStruct)


class _Collection(BaseModel):
    path: str = "./Types/"


class _FirmwaresKey(BaseModel):
    codec: str = "ascii"
    value: str = "00000000password"


class _Firmware(BaseModel):
    key: _FirmwaresKey = Field(default_factory=_FirmwaresKey)
    man: str = Field("KPZ")
    path: Path = Field(Path("./Firmwares/firmwares.dat"))

    @field_serializer("path")
    def serialize1_path(self, path: Path) -> str:
        return str(path)


class _AmNames(BaseModel):
    """all attributes and methods names of classes"""
    APN: str = "APN"
    CRC_NOK_frames_counter: str = "CRC NOK frames counter"
    CRC_OK_frames_counter: str = "CRC OK frames counter"
    DL_reference: str = "DL reference"
    FCS_NOK_frames_counter: str = "FCS NOK frames counter"
    FCS_OK_frames_counter: str = "FCS OK frames counter"
    IPCP_options: str = "IPCP options"
    IP_address: str = "IP address"
    IP_options: str = "IP options"
    IP_reference: str = "IP reference"
    LCP_options: str = "LCP options"
    LLS_secret: str = "LLS secret"
    LTE_network_parameters: str = "LTE network parameters"
    LTE_quality_of_service: str = "LTE quality of service"
    M_Bus_Data_Header_Type: str = "M-Bus Data Header Type"
    MAC_address: str = "MAC address"
    MMS: str = "MMS"
    M_Bus_port_communication_state: str = "M Bus port communication state"
    M_Bus_profile_selection: str = "M Bus profile selection"
    PHY_reference: str = "PHY reference"
    PIN_code: str = "PIN code"
    PPP_authentication: str = "PPP authentication"
    SAP_assignment_list: str = "SAP assignment list"
    TCP_UDP_port: str = "TCP UDP port"
    access_number: str = "access number"
    access_rights_list: str = "access rights list"
    account_activation_time: str = "account activation time"
    account_closure_time: str = "account closure time"
    account_mode_and_status: str = "account mode and status"
    acknowledgement_time_t1: str = "acknowledgement time t1"
    acknowledgement_timer: str = "acknowledgement timer"
    actions: str = "actions"
    activate_account: str = "activate account"
    activate_passive_calendar: str = "activate passive calendar"
    activate_passive_calendar_time: str = "activate passive calendar time"
    activate_passive_unit_charge: str = "activate passive unit charge"
    activated: str = "activated"
    activation_status: str = "activation status"
    active_initiator: str = "active initiator"
    active_mask: str = "active mask"
    add_IPv6_address: str = "add IPv6 address"
    add_authentication_key: str = "add authentication key"
    add_function: str = "add function"
    add_mask: str = "add mask"
    add_mc_IP_address: str = "add mc IP address"
    add_object: str = "add object"
    add_parameter: str = "add parameter"
    add_register: str = "add register"
    add_user: str = "add user"
    addr_state: str = "addr state"
    address_config_mode: str = "address config mode"
    address_mask: str = "address mask"
    adjacent_cell: str = "adjacent cell"
    adjust_to_measuring_period: str = "adjust to measuring period"
    adjust_to_minute: str = "adjust to minute"
    adjust_to_preset_time: str = "adjust to preset time"
    adjust_to_quarter: str = "adjust to quarter"
    adjustment_method: str = "adjustment method"
    aggregated_debt: str = "aggregated debt"
    alarm: str = "alarm"
    allowed_failed_attempts: str = "allowed failed attempts"
    amount_to_clear: str = "amount to clear"
    application_context_name: str = "application context name"
    array_object_list: str = "array object list"
    associated_partners_id: str = "associated partners id"
    association_status: str = "association status"
    authentication_keys: str = "authentication keys"
    authentication_mechanism_name: str = "authentication mechanism name"
    authentication_method: str = "authentication method"
    avail_baud: str = "avail baud"
    available_credit: str = "available credit"
    base_node_address: str = "base node address"
    broadcast_frames_counter: str = "broadcast frames counter"
    buffer: str = "buffer"
    bus_address: str = "bus address"
    busy_state_timer: str = "busy state timer"
    calendar_name_active: str = "calendar name active"
    calendar_name_passive: str = "calendar name passive"
    calling_window: str = "calling window"
    capture: str = "capture"
    capture_definition: str = "capture definition"
    capture_method: str = "capture method"
    capture_objects: str = "capture objects"
    capture_period: str = "capture period"
    capture_time: str = "capture time"
    cell_info: str = "cell info"
    certificates: str = "certificates"
    change_HLS_secret: str = "change HLS secret"
    change_secret: str = "change secret"
    changed_parameter: str = "changed parameter"
    channel_Id: str = "channel Id"
    charge_configuration: str = "charge configuration"
    charge_reference_list: str = "charge reference list"
    charge_type: str = "charge type"
    clearance_threshold: str = "clearance threshold"
    client_key: str = "client key"
    client_system_title: str = "client system title"
    clock_base: str = "clock base"
    close_account: str = "close account"
    collect: str = "collect"
    comm_speed: str = "comm speed"
    communication_window: str = "communication window"
    compact_buffer: str = "compact buffer"
    configuration: str = "configuration"
    confirmation_parameters: str = "confirmation parameters"
    connect: str = "connect"
    connect_logical_device: str = "connect logical device"
    control_mode: str = "control mode"
    control_state: str = "control state"
    credit_available_threshold: str = "credit available threshold"
    credit_charge_configuration: str = "credit charge configuration"
    credit_configuration: str = "credit configuration"
    credit_reference_list: str = "credit reference list"
    credit_status: str = "credit status"
    credit_type: str = "credit type"
    cs_attachment: str = "cs attachment"
    cumulative_failed_attempts: str = "cumulative failed attempts"
    currency: str = "currency"
    current_average_value: str = "current average value"
    current_credit_amount: str = "current credit amount"
    current_credit_in_use: str = "current credit in use"
    current_credit_status: str = "current credit status"
    current_user: str = "current user"
    data_send: str = "data send"
    day_profile_table_active: str = "day profile table active"
    day_profile_table_passive: str = "day profile table passive"
    daylight_savings_begin: str = "daylight savings begin"
    daylight_savings_deviation: str = "daylight savings deviation"
    daylight_savings_enabled: str = "daylight savings enabled"
    daylight_savings_end: str = "daylight savings end"
    default_baud: str = "default baud"
    default_mode: str = "default mode"
    delete: str = "delete"
    delete_authentication_key: str = "delete authentication key"
    delete_mask: str = "delete mask"
    delete_mc_IP_address: str = "delete mc IP address"
    delete_parameter: str = "delete parameter"
    delta_electrical_phase: str = "delta electrical phase"
    destination_list: str = "destination list"
    desynchronization_listing: str = "desynchronization listing"
    device_addr: str = "device addr"
    device_address: str = "device address"
    device_type: str = "device type"
    emergency_profile: str = "emergency profile"
    emergency_profile_active: str = "emergency profile active"
    emergency_profile_group_id_list: str = "emergency profile group id list"
    enable_disable: str = "enable disable"
    encryption_key_status: str = "encryption key status"
    enter: str = "enter"
    entries: str = "entries"
    entries_in_use: str = "entries in use"
    execute: str = "execute"
    executed_script: str = "executed script"
    execution_time: str = "execution time"
    export_certificate: str = "export certificate"
    failed_attempts: str = "failed attempts"
    frequencies: str = "frequencies"
    function_list: str = "function list"
    gateway_IP_address: str = "gateway IP address"
    gateway_IPv6_addresses: str = "gateway IPv6 addresses"
    generate_certificate_request: str = "generate certificate request"
    generate_key_pair: str = "generate key pair"
    get_nbof_mc_IP_addresses: str = "get nbof mc IP addresses"
    get_protected_attributes: str = "get protected attributes"
    global_key_transfer: str = "global key transfer"
    hash_algorithm_id: str = "hash algorithm id"
    identification_number: str = "identification number"
    image_activate: str = "image activate"
    image_block_size: str = "image block size"
    image_block_transfer: str = "image block transfer"
    image_first_not_transferred_block_number: str = "image first not transferred block number"
    image_to_activate_info: str = "image to activate info"
    image_transfer_enabled: str = "image transfer enabled"
    image_transfer_initiate: str = "image transfer initiate"
    image_transfer_status: str = "image transfer status"
    image_transferred_blocks_status: str = "image transferred blocks status"
    image_verify: str = "image verify"
    import_certificate: str = "import certificate"
    inactivity_time_out: str = "inactivity time out"
    initial_lockout_time: str = "initial lockout time"
    initialization_string: str = "initialization string"
    initiator_electrical_phase: str = "initiator electrical phase"
    initiator_mac_address: str = "initiator mac address"
    insert: str = "insert"
    insert_entry: str = "insert entry"
    inter_octet_time_out: str = "inter octet time out"
    invoke_credit: str = "invoke credit"
    invoke_protected_method: str = "invoke protected method"
    key_agreement: str = "key agreement"
    key_transfer: str = "key transfer"
    last_average_value: str = "last average value"
    last_collection_amount: str = "last collection amount"
    last_collection_time: str = "last collection time"
    last_confirmation_date_time: str = "last confirmation date time"
    last_outcome: str = "last outcome"
    length: str = "length"
    limit: str = "limit"
    link_status: str = "link status"
    list_of_allowed_callers: str = "list of allowed callers"
    listening_window: str = "listening window"
    logical_name: str = "logical name"
    login_password: str = "login password"
    low_credit_threshold: str = "low credit threshold"
    mac_LNID: str = "mac LNID"
    mac_LSID: str = "mac LSID"
    mac_SID: str = "mac SID"
    mac_SNA: str = "mac SNA"
    mac_address: str = "mac address"
    mac_beacon_rx_frequency: str = "mac beacon rx frequency"
    mac_beacon_rx_slot: str = "mac beacon rx slot"
    mac_beacon_slot_count: str = "mac beacon slot count"
    mac_beacon_tx_frequency: str = "mac beacon tx frequency"
    mac_beacon_tx_slot: str = "mac beacon tx slot"
    mac_beacons_per_frame: str = "mac beacons per frame"
    mac_capabilities: str = "mac capabilities"
    mac_csma_ch_busy_count: str = "mac csma ch busy count"
    mac_csma_fail_count: str = "mac csma fail count"
    mac_ctl_re_tx_timer: str = "mac ctl re tx timer"
    mac_group_addresses: str = "mac group addresses"
    mac_max_ctl_re_tx: str = "mac max ctl re tx"
    mac_max_promotion_pdu: str = "mac max promotion pdu"
    mac_min_switch_search_time: str = "mac min switch search time"
    mac_node_hierarchy_level: str = "mac node hierarchy level"
    mac_promotion_pdu_tx_period: str = "mac promotion pdu tx period"
    mac_rx_ctrl_pkt_count: str = "mac rx ctrl pkt count"
    mac_rx_data_pkt_count: str = "mac rx data pkt count"
    mac_scp_length: str = "mac scp length"
    mac_scp_max_tx_attempts: str = "mac scp max tx attempts"
    mac_state: str = "mac state"
    mac_tx_ctrl_pkt_count: str = "mac tx ctrl pkt count"
    mac_tx_data_pkt_count: str = "mac tx data pkt count"
    manufacturer_id: str = "manufacturer id"
    mapping_table: str = "mapping table"
    mask_list: str = "mask list"
    max_frame_length: str = "max frame length"
    max_info_field_length_receive: str = "max info field length receive"
    max_info_field_length_transmit: str = "max info field length transmit"
    max_lockout_time: str = "max lockout time"
    max_number_transmissions_n2: str = "max number transmissions n2"
    max_number_transmissions_n4: str = "max number transmissions n4"
    max_octets_acn_pdu_n3: str = "max octets acn pdu n3"
    max_octets_i_pdu_n1: str = "max octets i pdu n1"
    max_octets_ui_pdu: str = "max octets ui pdu"
    max_pdu_size: str = "max pdu size"
    max_provision: str = "max provision"
    max_provision_period: str = "max provision period"
    max_receiving_gain: str = "max receiving gain"
    max_transmitting_gain: str = "max transmitting gain"
    mbus_port_reference: str = "mbus port reference"
    metrological_identification: str = "metrological identification"
    min_delta_credit: str = "min delta credit"
    min_over_threshold_duration: str = "min over threshold duration"
    min_under_threshold_duration: str = "min under threshold duration"
    mode: str = "mode"
    modem_profile: str = "modem profile"
    monitored_value: str = "monitored value"
    most_recent_requests_table: str = "most recent requests table"
    multicast_IP_address: str = "multicast IP address"
    multicast_IPv6_addresses: str = "multicast IPv6 addresses"
    nb_of_sim_conn: str = "nb of sim conn"
    neighbor_discovery_setup: str = "neighbor discovery setup"
    next_credit_available_threshold: str = "next credit available threshold"
    next_period: str = "next period"
    number_of_calls: str = "number of calls"
    number_of_periods: str = "number of periods"
    number_of_retries: str = "number of retries"
    number_of_rings: str = "number of rings"
    object_list: str = "object list"
    operator: str = "operator"
    output_state: str = "output state"
    output_type: str = "output type"
    p_bit_timer: str = "p bit timer"
    parameter_list: str = "parameter list"
    parameter_list_name: str = "parameter list name"
    parameter_value_digest: str = "parameter value digest"
    parameter_values: str = "parameter values"
    pass_p1: str = "pass p1"
    pass_p2: str = "pass p2"
    pass_w5: str = "pass w5"
    period: str = "period"
    permission_table: str = "permission table"
    phy_stats_crc_fail_count: str = "phy stats crc fail count"
    phy_stats_crc_incorrect_count: str = "phy stats crc incorrect count"
    phy_stats_rx_drop_count: str = "phy stats rx drop count"
    phy_stats_tx_drop_count: str = "phy stats tx drop count"
    port_reference: str = "port reference"
    preset_adjusting_time: str = "preset adjusting time"
    preset_credit_amount: str = "preset credit amount"
    primary_DNS_address: str = "primary DNS address"
    primary_address: str = "primary address"
    primary_address_list: str = "primary address list"
    priority: str = "priority"
    processed_value: str = "processed value"
    processed_value_actions: str = "processed value actions"
    processed_value_thresholds: str = "processed value thresholds"
    profile_entries: str = "profile entries"
    prop_baud: str = "prop baud"
    proportion: str = "proportion"
    protection_buffer: str = "protection buffer"
    protection_mode: str = "protection mode"
    protection_object_list: str = "protection object list"
    protection_parameters_get: str = "protection parameters get"
    protection_parameters_set: str = "protection parameters set"
    protection_status: str = "protection status"
    ps_status: str = "ps status"
    push: str = "push"
    push_client_sap: str = "push client sap"
    push_object_list: str = "push object list"
    push_operation_method: str = "push operation method"
    push_protection_parameters: str = "push protection parameters"
    quality_of_service: str = "quality of service"
    randomisation_start_interval: str = "randomisation start interval"
    raw_value: str = "raw value"
    raw_value_actions: str = "raw value actions"
    raw_value_thresholds: str = "raw value thresholds"
    read_by_logicalname: str = "read by logical name"
    receive_lifetime_var_t2: str = "receive lifetime var t2"
    receive_window_size_rw: str = "receive window size rw"
    received_signal_strength: str = "received signal strength"
    register_assignment: str = "register assignment"
    reject_timer: str = "reject timer"
    remote_disconnect: str = "remote disconnect"
    remote_reconnect: str = "remote reconnect"
    remove_IPv6_address: str = "remove IPv6 address"
    remove_certificate: str = "remove certificate"
    remove_entries: str = "remove entries"
    remove_function: str = "remove function"
    remove_object: str = "remove object"
    remove_user: str = "remove user"
    repeater: str = "repeater"
    repeater_status: str = "repeater status"
    repetition_delay: str = "repetition delay"
    repetitions: str = "repetitions"
    repetitions_counter: str = "repetitions counter"
    reply_status_list: str = "reply status list"
    reply_to_HLS_authentication: str = "reply to HLS authentication"
    reporting_system_list: str = "reporting system list"
    request_action: str = "request action"
    required_protection: str = "required protection"
    reset: str = "reset"
    reset_NEW_not_synchronized: str = "reset NEW not synchronized"
    reset_account: str = "reset account"
    reset_alarm: str = "reset alarm"
    response_time: str = "response time"
    retrieve_entries: str = "retrieve entries"
    retrieve_number_of_entries: str = "retrieve number of entries"
    scaler_unit: str = "scaler unit"
    scripts: str = "scripts"
    sealing_method: str = "sealing method"
    search_initiator_threshold: str = "search initiator threshold"
    search_initiator_timeout: str = "search initiator timeout"
    season_profile_active: str = "season profile active"
    season_profile_passive: str = "season profile passive"
    secondary_DNS_address: str = "secondary DNS address"
    secret: str = "secret"
    security_activate: str = "security activate"
    security_policy: str = "security policy"
    security_setup_reference: str = "security setup reference"
    security_suite: str = "security suite"
    send_destination_and_method: str = "send destination and method"
    sender_address: str = "sender address"
    serial_number: str = "serial number"
    server_address: str = "server address"
    server_port: str = "server port"
    server_system_title: str = "server system title"
    service_node_address: str = "service node address"
    set_amount_to_value: str = "set amount to value"
    set_encryption_key: str = "set encryption key"
    set_function_status: str = "set function status"
    set_protected_attributes: str = "set protected attributes"
    set_total_amount_remaining: str = "set total amount remaining"
    shift_time: str = "shift time"
    slave_deinstall: str = "slave deinstall"
    slave_install: str = "slave install"
    sort_method: str = "sort method"
    sort_object: str = "sort object"
    start_time_current: str = "start time current"
    status: str = "status"
    status_word: str = "status word"
    steepness_factor: str = "steepness factor"
    subnet_mask: str = "subnet mask"
    synchronization_confirmation_timeout: str = "synchronization confirmation timeout"
    synchronization_locked: str = "synchronization locked"
    synchronization_register: str = "synchronization register"
    synchronize: str = "synchronize"
    synchronize_clock: str = "synchronize clock"
    tabi_list: str = "tabi list"
    table_ID: str = "table ID"
    table_cell_definition: str = "table cell definition"
    table_cell_values: str = "table cell values"
    template_description: str = "template description"
    template_id: str = "template id"
    threshold_active: str = "threshold active"
    threshold_emergency: str = "threshold emergency"
    threshold_normal: str = "threshold normal"
    thresholds: str = "thresholds"
    time: str = "time"
    time_out_frame_not_OK: str = "time out frame not OK"
    time_out_not_addressed: str = "time out not addressed"
    time_zone: str = "time zone"
    token: str = "token"
    token_delivery_method: str = "token delivery method"
    token_description: str = "token description"
    token_gateway_configuration: str = "token gateway configuration"
    token_status: str = "token status"
    token_time: str = "token time"
    total_amount_paid: str = "total amount paid"
    total_amount_remaining: str = "total amount remaining"
    traffic_class: str = "traffic class"
    transfer_key: str = "transfer key"
    transmission_speed: str = "transmission speed"
    transmissions_counter: str = "transmissions counter"
    transmit_lifetime_var_t3: str = "transmit lifetime var t3"
    transmit_window_size_k: str = "transmit window size k"
    type: str = "type"
    unicast_IPv6_addresses: str = "unicast IPv6 addresses"
    unit_charge_activation_time: str = "unit charge activation time"
    unit_charge_active: str = "unit charge active"
    unit_charge_passive: str = "unit charge passive"
    update_amount: str = "update amount"
    update_entry: str = "update entry"
    update_total_amount_remaining: str = "update total amount remaining"
    update_unit_charge: str = "update unit charge"
    use_DHCP_flag: str = "use DHCP flag"
    user_list: str = "user list"
    user_name: str = "user name"
    value: str = "value"
    version: str = "version"
    warning_threshold: str = "warning threshold"
    week_profile_table_active: str = "week profile table active"
    week_profile_table_passive: str = "week profile table passive"
    weightings_table: str = "weightings table"
    windows_size_receive: str = "windows size receive"
    windows_size_transmit: str = "windows size transmit"
    xDLMS_context_info: str = "xDLMS context info"


class Conformance(BaseModel):
    reserved_zero: str = "reserved-zero"
    general_protection: str = "general-protection"
    general_block_transfer: str = "general-block-transfer"
    read: str = "read"
    write: str = "write"
    unconfirmed_write: str = "unconfirmed-write"
    reserved_six: str = "reserved-six"
    reserved_seven: str = "reserved-seven"
    attribute0_supported_with_set: str = "attribute0-supported-with-set"
    priority_mgmt_supported: str = "priority-mgmt-supported"
    attribute0_supported_with_get: str = "attribute0-supported-with-get"
    block_transfer_with_get_or_read: str = "block-transfer-with-get-or-read"
    block_transfer_with_set_or_write: str = "block-transfer-with-set-or-write"
    block_transfer_with_action: str = "block-transfer-with-action"
    multiple_references: str = "multiple-references"
    information_report: str = "information-report"
    data_notification: str = "data-notification"
    access: str = "access"
    parameterized_access: str = "parameterized-access"
    get: str = "get"
    set: str = "set"
    selective_access: str = "selective-access"
    event_notification: str = "event-notification"
    action: str = "action"


class Settings(BaseModel):
    collection: _Collection = Field(default_factory=_Collection)
    report: _Report = Field(default_factory=_Report)
    firmwares: list[_Firmware] = Field(default_factory=list)
    am_names: _AmNames = Field(default_factory=_AmNames)
    class_name: dict[int, str] = Field(default={1: "Data"})


if not os.path.isfile(path := ".//config.toml"):
    path = F"{os.path.dirname(__file__)}{path}"
elif os.path.isfile(path):
    with open(path, "rb") as f:
        toml_data = tomllib.load(f)
        data = toml_data.get("DLMS", {})
        print(f"Find configuration <config.toml> with path: {f}")
        settings = Settings(**data)
else:
    print("NOT FIND CONFIGURATION: <config.toml>")
    toml_data = {}
    settings = Settings()


# remove in future


def version():
    return "0.2.0"


class Language(Enum):
    ENGLISH = 'English'
    RUSSIAN = 'Russian'


__current_language = Language.RUSSIAN


def set_current_language(value: str):
    global __current_language
    __current_language = Language(value)


def get_current_language() -> Language:
    return __current_language
