import re

# Define CIM export file path, optional -- this file is used automate creation
# of Devices file (device_csv_file_path) and related tag map files
cim_export_file_path = "C:\\Users\\rcarroll\\Desktop\\Dominion\\DNP_openPDC_config_from_CIM_07232025.csv"

# Source devices CSV file (include path if not in same directory as script):
device_csv_file_path = "Devices.csv"
default_dnp3_port = 20006

# openPDC database connection details (must be ODBC-type connection):
server_name = ".\\SQLEXPRESS"
db_name = "openPDC"
db_connection_string = (
    f"mssql+pyodbc://{server_name}/{db_name}?trusted_connection=yes&driver=ODBC+Driver+17+for+SQL+Server"
)
is_sql_server = True

# Target historian for measurements:
target_source = "PPA"

# Default company acronym:
company_acronym = "DOM"

# Version 2011 of IEEE C37.118 allows analog and digital fields to be 255 characters long,
# older versions of the standard only allow 16 characters:
ieee_c37_118_version = 2011

# Determines if DNP3 quality flags should be mapped to measurement state flags:
# Note: option works to include flags for IEEE 2664 (STTP) style outputs
map_quality_to_state_flags = True

# Determines if DNP3 quality flags should be published as separate measurement outputs:
# Note: option works to include flags for IEEE C37.1118 or IEEE 2664 (STTP) style outputs
publish_flags_as_separate_measurements = True

# Regular expression pattern used to match tag names for quality flag outputs:
# Note: expression expects capture groups "TagName" and "SignalType"
# In the case of Dominion, tag names do not include the ":ALOG" or ":DIGI" suffix
# so the pattern is setup to make that portion optional:
tag_match_pattern = r"(?<TagName>.+?)((?<SignalType>:(ALOG|DIGI))\d+)?"

# Suffix to append to the tag name for DNP3 quality flag measurement outputs:
quality_tag_suffix = "!FLAGS"

# Interval, in seconds, at which the adapter will poll the DNP3 device:
# Note: set to zero for on-change only
polling_interval = 2.0

# Valid +/- time range, in seconds, for calculation input measurement values before
# they are considered stale -- keep value small, e.g., 2-4 seconds, only consequence
# is assigning bad time quality to the calculated output measurement
valid_time_range = 4.0

# Define I/O directories (include path if not relative to script):
output_directory = "dnp3config/"
template_directory = "template/"
tag_map_directory = "tagmaps/"

# Define path to "openPDCConsole.exe" application:
open_pdc_console_path = "C:\\Program Files\\openPDC\\openPDCConsole.exe"

# Define flag that determines if adapters should be initialized after configuration:
# Note: Updated DNP3 config files must be loaded into openPDC installation folder before
# adapter can be initialized. Suggest setting "output_directory" to openPDC installation
# folder, e.g., "C:\\Program Files\\openPDC\\DNP3Config\\", before enabling this option.
# Alternately, this script can be run from openPDC install folder to use relative paths.
initialize_adapters = True

# Define comment character for CSV file rows
comment_char = "#"


# Gets a clean identifier
def get_clean_identifier(value: str) -> str:
    """
    Gets a clean version of the given value by removing characters that are
    invalid in a time-series framework identifier, replacing spaces with
    underscores, and converting value to uppercase.

    Args:
        value (str): The value to be cleaned.

    Returns:
        str: The cleaned identifier.
    """
    return re.sub(r"[^A-Z0-9\-!_\.@#\$]+", "", value.replace(" ", "_").upper())
