# This file is part of OpenModelica.
#
# Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
# c/o Linköpings universitet, Department of Computer and Information Science,
# SE-58183 Linköping, Sweden.
#
# All rights reserved.
#
# THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
# THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
# ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
# RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
# VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
#
# The OpenModelica software and the OSMC (Open Source Modelica Consortium)
# Public License (OSMC-PL) are obtained from OSMC, either from the above
# address, from the URLs:
# http://www.openmodelica.org or
# https://github.com/OpenModelica/ or
# http://www.ida.liu.se/projects/OpenModelica,
# and in the OpenModelica distribution.
#
# GNU AGPL version 3 is obtained from:
# https://www.gnu.org/licenses/licenses.html#GPL
#
# This program is distributed WITHOUT ANY WARRANTY; without
# even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
# IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
#
# See the full OSMC Public License conditions for more details.

from enum import Enum
from sqlite3 import Binary
from typing import Union

from OMSimulator.cref import CRef


class Causality(Enum):
  '''Enumeration for signal causality (oms_causality_enu_t).'''
  input = 0
  output = 1
  parameter = 2
  calculatedParameter = 3
  local = 4
  independent = 5


class SignalType(Enum):
  '''Enumeration for signal types (oms_signal_type_enu_t).'''
  Real = 0
  Integer = 1
  Boolean = 2
  String = 3
  Enumeration = 4
  ## fmi3 types
  Float32   = 5
  Float64   = 6
  Int8      = 7
  UInt8     = 8
  Int16     = 9
  UInt16    = 10
  Int32     = 11
  UInt32    = 12
  Int64     = 13
  UInt64    = 14
  Binary    = 15

## class to represent the numeric type of a signal, which is relevant for FMI3 variables, maintain the order to refect c code enum oms_signal_numeric_type_enu_t
class SignalNumericType(Enum):
  FLOAT32 = 0    # Represents fmi3Float32
  FLOAT64 = 1    # Represents fmi3Float64
  INT8    = 2    # Represents fmi3Int8
  UINT8   = 3    # Represents fmi3UInt8
  INT16   = 4    # Represents fmi3Int16
  UINT16  = 5    # Represents fmi3UInt16
  INT32   = 6    # Represents fmi3Int32
  UINT32  = 7    # Represents fmi3UInt32
  INT64   = 8    # Represents fmi3Int64
  UINT64  = 9    # Represents fmi3UInt64
  NONE    = 10   # Represents no numeric type (e.g., for Boolean, String)

class FMI3Type:
  """Base class for all FMI3 types."""
  def __init__(self, value):
    self.value = value

  def __repr__(self):
    return f"{self.__class__.__name__}({self.value})"


# Float types
class Float64(FMI3Type): pass
class Float32(FMI3Type): pass

# Integer types
class Int64(FMI3Type): pass
class Int32(FMI3Type): pass
class Int16(FMI3Type): pass
class Int8(FMI3Type): pass

# Unsigned Integer types
class UInt64(FMI3Type): pass
class UInt32(FMI3Type): pass
class UInt16(FMI3Type): pass
class UInt8(FMI3Type): pass

class Binary(FMI3Type): pass

class Variable:
  '''Class for storing variable information'''
  def __init__(self, name: Union[str, CRef], description : str, valueReference: Union[str, int], causality, variability, signal_type, unit, start_value, declaredType):
    self.name = CRef(name)
    self.description = description
    self.valueReference = int(valueReference)
    self.causality = causality if isinstance(causality, Causality) else Causality[causality]
    self.variability = variability
    self.signal_type = signal_type if isinstance(signal_type, SignalType) else SignalType[signal_type]
    self.unit = unit
    self.modelDescriptionStartValue = start_value
    self.declaredType = declaredType
    self.unitDefinition = []
    self.enumerationDefinition = []

  def isInput(self):
    return self.causality == Causality.input

  def isOutput(self):
    return self.causality == Causality.output

  def isParameter(self):
    return self.causality == Causality.parameter

  def isCalculatedParameter(self):
    return self.causality == Causality.calculatedParameter
