# generated by datamodel-codegen:
#   filename:  Config.schema.json

from __future__ import annotations

from datetime import datetime
from typing import List, Optional, Union

from pydantic import BaseModel, Field


class Results(BaseModel):
    basin: str = "results/basin.arrow"
    flow: str = "results/flow.arrow"
    control: str = "results/control.arrow"
    outstate: Optional[str] = None
    compression: str = "zstd"
    compression_level: int = 6


class Solver(BaseModel):
    algorithm: str = "QNDF"
    saveat: Union[float, List[float]] = []
    adaptive: bool = True
    dt: Optional[float] = None
    dtmin: Optional[float] = None
    dtmax: Optional[float] = None
    force_dtmin: bool = False
    abstol: float = 1e-06
    reltol: float = 0.001
    maxiters: int = 1000000000
    sparse: bool = True
    autodiff: bool = True


class Logging(BaseModel):
    verbosity: str = "info"
    timing: bool = False


class Terminal(BaseModel):
    static: Optional[str] = None


class PidControl(BaseModel):
    static: Optional[str] = None
    time: Optional[str] = None


class LevelBoundary(BaseModel):
    static: Optional[str] = None
    time: Optional[str] = None


class Pump(BaseModel):
    static: Optional[str] = None


class TabulatedRatingCurve(BaseModel):
    static: Optional[str] = None
    time: Optional[str] = None


class User(BaseModel):
    static: Optional[str] = None
    time: Optional[str] = None


class FlowBoundary(BaseModel):
    static: Optional[str] = None
    time: Optional[str] = None


class Basin(BaseModel):
    profile: Optional[str] = None
    state: Optional[str] = None
    static: Optional[str] = None
    time: Optional[str] = None


class ManningResistance(BaseModel):
    static: Optional[str] = None


class DiscreteControl(BaseModel):
    condition: Optional[str] = None
    logic: Optional[str] = None


class Outlet(BaseModel):
    static: Optional[str] = None


class LinearResistance(BaseModel):
    static: Optional[str] = None


class FractionalFlow(BaseModel):
    static: Optional[str] = None


class Config(BaseModel):
    starttime: datetime
    endtime: datetime
    update_timestep: float = 86400
    relative_dir: str = "."
    input_dir: str = "."
    results_dir: str = "."
    database: str
    results: Results = Field(
        default_factory=lambda: Results.parse_obj(
            {
                "basin": "results/basin.arrow",
                "flow": "results/flow.arrow",
                "control": "results/control.arrow",
                "outstate": None,
                "compression": "zstd",
                "compression_level": 6,
            }
        )
    )
    solver: Solver = Field(
        default_factory=lambda: Solver.parse_obj(
            {
                "algorithm": "QNDF",
                "saveat": [],
                "adaptive": True,
                "dt": None,
                "dtmin": None,
                "dtmax": None,
                "force_dtmin": False,
                "abstol": 1e-06,
                "reltol": 0.001,
                "maxiters": 1000000000,
                "sparse": True,
                "autodiff": True,
            }
        )
    )
    logging: Logging = Field(
        default_factory=lambda: Logging.parse_obj(
            {"verbosity": {"level": 0}, "timing": False}
        )
    )
    terminal: Terminal = Field(
        default_factory=lambda: Terminal.parse_obj({"static": None})
    )
    pid_control: PidControl = Field(
        default_factory=lambda: PidControl.parse_obj({"static": None, "time": None})
    )
    level_boundary: LevelBoundary = Field(
        default_factory=lambda: LevelBoundary.parse_obj({"static": None, "time": None})
    )
    pump: Pump = Field(default_factory=lambda: Pump.parse_obj({"static": None}))
    tabulated_rating_curve: TabulatedRatingCurve = Field(
        default_factory=lambda: TabulatedRatingCurve.parse_obj(
            {"static": None, "time": None}
        )
    )
    user: User = Field(
        default_factory=lambda: User.parse_obj({"static": None, "time": None})
    )
    flow_boundary: FlowBoundary = Field(
        default_factory=lambda: FlowBoundary.parse_obj({"static": None, "time": None})
    )
    basin: Basin = Field(
        default_factory=lambda: Basin.parse_obj(
            {"profile": None, "state": None, "static": None, "time": None}
        )
    )
    manning_resistance: ManningResistance = Field(
        default_factory=lambda: ManningResistance.parse_obj({"static": None})
    )
    discrete_control: DiscreteControl = Field(
        default_factory=lambda: DiscreteControl.parse_obj(
            {"condition": None, "logic": None}
        )
    )
    outlet: Outlet = Field(default_factory=lambda: Outlet.parse_obj({"static": None}))
    linear_resistance: LinearResistance = Field(
        default_factory=lambda: LinearResistance.parse_obj({"static": None})
    )
    fractional_flow: FractionalFlow = Field(
        default_factory=lambda: FractionalFlow.parse_obj({"static": None})
    )
