def getColumnOrder(columns_config):
	visible_columns = [k for k, v in sorted(columns_config.items(), key=lambda x: x[1]["order"]) 
                   if v["enabled"]]
	return visible_columns         
	
def fromObjToDS(data, column_order=None):
	"""
    Converts a list of dictionaries into an Ignition PyDataSet.
    
    Parameters:
        data: list[dict] - list of dictionaries where keys are column names
        column_order: list[str] (optional) - explicit column order. 
                      If None, uses the keys from the fi row.
    
    Returns:
        PyDataSet - Ignition dataset object
    """
	if len(data)== 0:
	    # Return empty dataset with no columns if input is invalid/empty

	    return system.dataset.toDataSet([], [])
	
	# Determine column names
	if column_order is not None:
	    headers = column_order
	else:
	    # Use keys from first dictionary (Python 3.7+ preserves insertion order)
	    headers = list(data[0].keys())
	
	# Build rows
	rows = []
	for row_dict in data:
	    # Create row tuple using the determined column order
	    row = []
	    for col in headers:
	        # Use .get() so missing keys become None (standard dataset behavior)
	        value = row_dict.get(col, None)
	        row.append(value)
	    rows.append(row)
	
	# Create the actual dataset	
	return system.dataset.toDataSet(headers, rows)
	
def true_keys(data):
	"""
	Returns a list of dictionary keys whose values are strictly True.
	
	Parameters:
	  data (dict): A dictionary with boolean values.
	
	Returns:
	  list[str]: A list of keys where the value is True, or an empty list
	             if none match.
	
	Example:
	  priorities = {
	      "diagnostic": True,
	      "low": False,
	      "medium": False,
	      "high": False,
	      "critical": False
	  }
	
	  result = true_keys(priorities)
	  # result => ['diagnostic']
	"""
	
	return [key for key, value in data.items() if value is True]
	
def parse_event_filter_to_query_states(events):
	"""
    Build a list of event state labels from the given filter.

    Input:
      events: A container supporting membership tests (e.g., set/list/dict keys),
              where possible keys are:
                - 'active'  -> include active states
                - 'cleared' -> include cleared states
                - 'acked'   -> refine to only acked states (removes *Unacked)

    Behavior:
      - If 'active' in events:  add ['activeUnacked']
      - If 'cleared' in events: add ['clearedUnacked']
      - If 'acked' in events:   remove any label containing 'Un' (i.e., keep only *Acked)

    Returns:
      list[str]: A list of labels, e.g.,
                 ['activeUnacked', 'activeAcked', 'clearedUnacked', 'clearedAcked']
                 reduced by the 'acked' refiner if present.

    Examples:
      parse_event_filter_to_query_states({'active'})
      -> ['ActiveUnacked', 'ActiveAcked']

      parse_event_filter_to_query_states({'cleared', 'acked'})
      -> ['ClearAcked']

      parse_event_filter_to_query_states({'active', 'cleared', 'acked'})
      -> ['ActiveAcked', 'ClearAcked']
      
      parse_event_filter_to_query_states({'active', 'cleared', 'acked'})
      -> ['ClearAcked', 'ActiveAcked']
	"""
	
	ret = []
	
	if 'active' in events:
		ret += ['ActiveUnacked']
		
	if 'cleared' in events:
		ret += ['ClearUnacked']
		
	if 'acked' in events:
		if len(ret) == 0:
			ret += ['ActiveAcked', 'ClearAcked']
		else:
			if 'active' in events:
				ret += ['ActiveAcked']
			if 'cleared' in events:
				ret += ['ClearAcked']

	return ret
