from pathlib import Path
from sbmlutils.io import read_sbml, write_sbml, validate_sbml

from sbmlutils.factory import *
from sbmlutils.metadata import *

import tempfile

model = Model(
    "example_model",
    units=Units,
    model_units = ModelUnits(
        time=Units.second,
        substance=Units.mole,
        extent=Units.mole,
        volume=Units.litre,
    ),
    compartments = [Compartment(sid="C", value=1.0)],
    species = [
        Species(
            sid="S1",
            initialConcentration=10.0,
            compartment="C",
            hasOnlySubstanceUnits=False,
        ),
        Species(
            sid="S2",
            initialConcentration=0.0,
            compartment="C",
            hasOnlySubstanceUnits=False,
        )
    ],
    parameters = [Parameter(sid="k1", value=1.0)],
    reactions = [
        Reaction(sid="R1", equation="S1 -> S2", formula=("k1 * S1", None))
    ],
)

# create the model as L3V1
with tempfile.TemporaryDirectory() as tmp_path:
    results = create_model(
        models=model,
        output_dir=Path(tmp_path),
        tmp=False,
        units_consistency=False,
        sbml_level=3,
        sbml_version=1,
    )
    # show level and version and print SBML
    doc = read_sbml(source=results.sbml_path, validate=False)
    sbml = write_sbml(doc)
    print(sbml)

"""
Explanation: SBML creator
sbmlutils provides helpers for the creation of SBML models from scratch.
Create model
The easist way to create a new model is by using a dictionary of information for the model creation.
End of explanation
"""


class U(Units):
    """UnitDefinitions."""
    
    mmole = UnitDefinition("mmole", "mmole")
    mmole_per_min = UnitDefinition("mmole_per_min", "mmole/min")


"""
Explanation: Units
It is highly recommended to annotate all units in the model. This allows automatic unit validation and unit conversions with the model.
Units are defined by subclassing the Units class. This provides the default SBML units and allows for code completion with units. Units are defined as attributes on the Units subclass.
End of explanation
"""


from sbmlutils.io import read_sbml, write_sbml, validate_sbml

from sbmlutils.factory import *
from sbmlutils.metadata import *

import tempfile

# model definition
md: ModelDict = {
        "sid": "level_version",
        "units": U,
        "model_units": ModelUnits(
            time=U.second,
            substance=U.mole,
            extent=U.mole,
            volume=U.liter,
        ),
        "compartments": [Compartment(sid="C", value=1.0)],
        "species": [
            Species(
                sid="S1",
                initialConcentration=10.0,
                compartment="C",
                hasOnlySubstanceUnits=False,
                boundaryCondition=True,
            )
        ],
        "parameters": [Parameter(sid="k1", value=1.0)],
        "reactions": [
            Reaction(sid="R1", equation="S1 ->", formula=("k1 * S1", None))
        ],
    }

supported_level_version = [
    (1, 1), (1, 2),
    (2, 1), (2, 2), (2, 3), (2, 4), (2, 5),
    (3, 1), (3, 2),
]

with tempfile.TemporaryDirectory() as tmp_path:

    for level, version in supported_level_version:
        # inject information
        md["sid"] = f"L{level}V{version}"
        results = create_model(
            models=Model(**md),
            output_dir=Path(tmp_path),
            tmp=False,
            units_consistency=False,
            sbml_level=level,
            sbml_version=version,
        )
        doc = read_sbml(source=results.sbml_path, validate=False)
        print(f"L{doc.getLevel()}V{doc.getVersion()}")
        if level == 3 and version == 1:
            sbml = write_sbml(doc)
            print("-" * 80)
            print(sbml)


"""
Explanation: SBML Levels and Versions
Models can be generated in all SBML levels and versions via the create_model function.
End of explanation
"""


