class MOHYSE(Raven):
    identifier = "mohyse"

    @dataclass
    class Params:
        par_x01: float = None
        par_x02: float = None
        par_x03: float = None
        par_x04: float = None
        par_x05: float = None
        par_x06: float = None
        par_x07: float = None
        par_x08: float = None
        par_x09: float = None
        par_x10: float = None

    @dataclass
    class DerivedParams:
        par_rezi_x10: float = None

    def __init__(self, *args, **kwds):
        super().__init__(*args, **kwds)

        self.config = Config(
            hrus=(GR4JCN.LandHRU(),),
            subbasins=(
                Sub(
                    subbasin_id=1,
                    name="sub_001",
                    downstream_id=-1,
                    profile="None",
                    gauged=True,
                ),
            ),
            params=MOHYSE.Params(),
            derived_params=MOHYSE.DerivedParams(),
        )

        self.config.rvp.tmpl = """
        #-----------------------------------------------------------------
        # Soil Classes
        #-----------------------------------------------------------------
        :SoilClasses
          :Attributes,
          :Units,
          TOPSOIL
          GWSOIL
        :EndSoilClasses

        #-----------------------------------------------------------------
        # Land Use Classes
        #-----------------------------------------------------------------
        :LandUseClasses,
          :Attributes,        IMPERM,    FOREST_COV,
          :Units,             frac,      frac,
          LU_ALL,             0.0,       1.0
        :EndLandUseClasses

        #-----------------------------------------------------------------
        # Vegetation Classes
        #-----------------------------------------------------------------
        :VegetationClasses,
          :Attributes,        MAX_HT,       MAX_LAI,    MAX_LEAF_COND,
          :Units,             m,            none,       mm_per_s,
         VEG_ALL,             0.0,          0.0,        0.0
        :EndVegetationClasses

        #-----------------------------------------------------------------
        # Soil Profiles
        #-----------------------------------------------------------------
        :SoilProfiles
                 LAKE, 0
                 ROCK, 0
               # DEFAULT_P,      2, TOPSOIL, MOHYSE_PARA_5, GWSOIL, 10.0
                 DEFAULT_P,      2, TOPSOIL,     {params.par_x05}, GWSOIL, 10.0
        :EndSoilProfiles

        #-----------------------------------------------------------------
        # Global Parameters
        #-----------------------------------------------------------------
        #:GlobalParameter      RAINSNOW_TEMP              -2.0
        :GlobalParameter       TOC_MULTIPLIER              1.0
        # :GlobalParameter     MOHYSE_PET_COEFF  MOHYSE_PARA_1
        :GlobalParameter       MOHYSE_PET_COEFF      {params.par_x01}

        #-----------------------------------------------------------------
        # Soil Parameters
        #-----------------------------------------------------------------
        :SoilParameterList
          :Parameters,        POROSITY,  PET_CORRECTION,        HBV_BETA,  BASEFLOW_COEFF,      PERC_COEFF,
               :Units,               -,               -,               -,             1/d,             1/d, # (units not generated by .rvp template)
            # TOPSOIL,            1.0 ,             1.0,             1.0,   MOHYSE_PARA_7,   MOHYSE_PARA_6,
            #  GWSOIL,            1.0 ,             1.0,             1.0,   MOHYSE_PARA_8,             0.0,
              TOPSOIL,            1.0 ,             1.0,             1.0,       {params.par_x07},       {params.par_x06},
               GWSOIL,            1.0 ,             1.0,             1.0,       {params.par_x08},             0.0,
        :EndSoilParameterList

        #-----------------------------------------------------------------
        # Land Use Parameters
        #-----------------------------------------------------------------
        :LandUseParameterList
          :Parameters,     MELT_FACTOR,       AET_COEFF, FOREST_SPARSENESS, DD_MELT_TEMP,
               :Units,          mm/d/K,            mm/d,                 -,         degC,
          # [DEFAULT],   MOHYSE_PARA_3,   MOHYSE_PARA_2,               0.0,MOHYSE_PARA_4,
            [DEFAULT],       {params.par_x03},       {params.par_x02},               0.0,    {params.par_x04},
        :EndLandUseParameterList

        #-----------------------------------------------------------------
        # Vegetation Parameters
        #-----------------------------------------------------------------
        :VegetationParameterList
          :Parameters,    SAI_HT_RATIO,  RAIN_ICEPT_PCT,  SNOW_ICEPT_PCT,
               :Units,               -,               -,               -,
            [DEFAULT],             0.0,             0.0,             0.0,
        :EndVegetationParameterList
        """

        self.config.rvi.tmpl = """
        :Calendar              {calendar}
        :RunName               {run_name}-{run_index}
        :StartDate             {start_date}
        :EndDate               {end_date}
        :TimeStep              {time_step}
        :Method                ORDERED_SERIES

        :SoilModel             SOIL_TWO_LAYER
        :PotentialMeltMethod   POTMELT_DEGREE_DAY
        :Routing               ROUTE_NONE
        :CatchmentRoute        ROUTE_GAMMA_CONVOLUTION
        :Evaporation           {evaporation}  # PET_MOHYSE
        :DirectEvaporation
        :RainSnowFraction      {rain_snow_fraction}

        :HydrologicProcesses
             :SoilEvaporation  SOILEVAP_LINEAR    SOIL[0]            ATMOSPHERE
             :SnowBalance      SNOBAL_SIMPLE_MELT SNOW PONDED_WATER
             :Precipitation    RAVEN_DEFAULT      ATMOS_PRECIP       MULTIPLE
             :Infiltration     INF_HBV            PONDED_WATER       SOIL[0]
             :Baseflow         BASE_LINEAR        SOIL[0]            SURFACE_WATER
             :Percolation      PERC_LINEAR        SOIL[0]            SOIL[1]
             :Baseflow         BASE_LINEAR        SOIL[1]            SURFACE_WATER
        :EndHydrologicProcesses

        #:CreateRVPTemplate

        # :Alias MOHYSE_PARA_1      1.5589    # :GlobalParameter         MOHYSE_PET_COEFF
        # :Alias MOHYSE_PARA_2	    0.9991    # LandUseParameterList --> AET_COEFF
        # :Alias MOHYSE_PARA_3	    2.1511    # LandUseParameterList --> MELT_FACTOR
        # :Alias MOHYSE_PARA_4	   -1.6101    # LandUseParameterList --> DD_MELT_TEMP
        # :Alias MOHYSE_PARA_5	    0.5000    # SoilProfiles         --> thickness of TOPSOIL (in mm????? must be m!!!)
        # :Alias MOHYSE_PARA_6	    0.1050    # SoilParameterList    --> PERC_COEFF (TOPSOIL)
        # :Alias MOHYSE_PARA_7	    0.0533    # SoilParameterList    --> BASEFLOW_COEFF (TOPSOIL)
        # :Alias MOHYSE_PARA_8	    0.0132    # SoilParameterList    --> BASEFLOW_COEFF (GWSOIL)
        # :Alias MOHYSE_PARA_9	    1.0474    # :SubBasinProperties  --> GAMMA_SHAPE
        # :Alias MOHYSE_PARA_10	    7.9628    # :SubBasinProperties  --> TIME_CONC = MOHYSE_PARA_10 / 0.3 = 26.542666666

        #---------------------------------------------------------
        # Output Options
        #
        #:WriteForcingFunctions
        :EvaluationMetrics {evaluation_metrics}
        :WriteNetcdfFormat  yes
        #:NoisyMode
        :SilentMode
        :PavicsMode
        {suppress_output}

        :NetCDFAttribute title Simulated river discharge
        :NetCDFAttribute history Created on {now} by Raven
        :NetCDFAttribute references  Craig, J.R., and the Raven Development Team, Raven user's and developer's manual (Version 2.8), URL: http://raven.uwaterloo.ca/ (2018).
        :NetCDFAttribute comment Raven Hydrological Framework version {raven_version}

        :NetCDFAttribute model_id mohyse

        :NetCDFAttribute time_frequency day
        :NetCDFAttribute time_coverage_start {start_date}
        :NetCDFAttribute time_coverage_end {end_date}
        """

        self.config.rvh.tmpl = """
        {subbasins}

        {hrus}

        :SubBasinProperties
        #                  1.0 / MOHYSE_PARA_10,   MOHYSE_PARA_9
           :Parameters,             GAMMA_SCALE,     GAMMA_SHAPE,
           :Units,                          1/d,               -
                      1,         {par_rezi_x10},       {par_x09}
        :EndSubBasinProperties
        """

        self.config.rvi.rain_snow_fraction = "RAINSNOW_DATA"
        self.config.rvi.evaporation = "PET_MOHYSE"

        # This is not stricly necessary it seems
        self.config.rvc.hru_states[1] = HRUState()
        self.config.rvc.basin_states[1] = BasinIndexCommand()

    def derived_parameters(self):
        self.config.rvp.derived_params.par_rezi_x10 = (
            1.0 / self.config.rvp.params.par_x10
        )

        # These need to be injected in the RVH
        self.config.rvh.par_rezi_x10 = self.config.rvp.derived_params.par_rezi_x10
        self.config.rvh.par_x09 = self.config.rvp.params.par_x09


class MOHYSE_OST(Ostrich, MOHYSE):
    _p = Path(__file__).parent / "ostrich-mohyse"
    templates = tuple(_p.glob("model/*.rv?")) + tuple(_p.glob("*.t??"))

    def __init__(self, *args, **kwds):
        super().__init__(*args, **kwds)
        self.rvi.suppress_output = True
        self.txt = Ost(
            algorithm="DDS",
            max_iterations=50,
            lowerBounds=MOHYSE.params(
                None, None, None, None, None, None, None, None, None, None
            ),
            upperBounds=MOHYSE.params(
                None, None, None, None, None, None, None, None, None, None
            ),
        )

    def derived_parameters(self):
        """  Derived parameters are computed by Ostrich.  """
        pass
