from enum import Enum
from typing import Literal


Forcings = Literal[
    "AIR_DENS",
    "AIR_PRES",
    "CLOUD_COVER",
    "DAY_ANGLE",
    "DAY_LENGTH",
    "ET_RADIA",
    "LW_INCOMING",
    "LW_RADIA_NET",
    "OW_PET",
    "PET",
    "PET_MONTH_AVE",
    "POTENTIAL_MELT",
    "PRECIP",
    "PRECIP_5DAY",
    "PRECIP_DAILY_AVE",
    "RAINFALL",
    "RECHARGE",
    "REL_HUMIDITY",
    "SHORTWAVE",
    "SNOWFALL",
    "SNOW_FRAC",
    "SUBDAILY_CORR",
    "SW_RADIA",
    "SW_RADIA_NET",
    "TEMP_AVE",
    "TEMP_AVE_UNC",
    "TEMP_DAILY_AVE",
    "TEMP_DAILY_MAX",
    "TEMP_DAILY_MIN",
    "TEMP_MAX",
    "TEMP_MAX_UNC",
    "TEMP_MIN",
    "TEMP_MIN_UNC",
    "TEMP_MONTH_AVE",
    "TEMP_MONTH_MAX",
    "TEMP_MONTH_MIN",
    "WIND_VEL",
]

# Allowed soil parameters
SoilParameters = Literal[
    "AIR_ENTRY_PRESSURE",
    "ALBEDO_DRY",
    "ALBEDO_WET",
    "BASEFLOW_COEFF",
    "BASEFLOW_COEFF2",
    "BASEFLOW_N",
    "BASEFLOW_THRESH",
    "BF_LOSS_FRACTION",
    "BULK_DENSITY",
    "B_EXP",
    "CLAPP N,CLAPP M",
    "CLAPP_B",
    "CLAY_CON",
    "EVAP_RES_FC",
    "FIELD_CAPACITY",
    "GR4J_X2",
    "GR4J_X3",
    "HBV_BETA",
    "HEAT_CAPACITY",
    "HYDRAUL_COND",
    "INTERFLOW_COEF",
    "MAX_BASEFLOW_RATE",
    "MAX_CAP_RISE_RATE",
    "MAX_INTERFLOW_RATE",
    "MAX_PERC_RATE",
    "ORG_CON",
    "PERC_COEFF",
    "PERC_N",
    "PET_CORRECTION",  # Not in Raven Docs Table A.3
    "POROSITY",
    "SAC_PERC_ALPHA",
    "SAC_PERC_EXPON",
    "SAC_PERC_PFREE",
    "SAND_CON",
    "SAT_RES",
    "SAT_WILT",
    "SHUTTLEWORTH_B",
    "SILT_CON",
    "STONE_FRAC",
    "STORAGE_THRESHOLD",
    "THERMAL_COND",
    "UBC_EVAL_SOIL_DEF",
    "UBC_INFIL_SOIL_DEF",
    "UNAVAIL_FRAC",
    "VIC ALPHA",
    "VIC_EVAP_GAMMA",
    "VIC_ZMAX",
    "VIZ_ZMIN",
    "WETTING_FRONT_PSI",
    "WILTING_PRESSURE",
]

StateVariables = Literal[
    "ATMOSPHERE",
    "ATMOS_PRECIP",
    "CANOPY",
    "CANOPY_SNOW",
    "CANOPY_TEMP",
    "COLD_CONTENT",
    "CONSTITUENT",
    "CONSTITUENT_SINK",
    "CONSTITUENT_SRC",
    "CONSTITUENT_SW",
    "CONVOLUTION",
    "CONV_STOR",
    "CROP_HEAT_UNITS",
    "CUM_INFIL",
    "CUM_SNOWMELT",
    "DEPRESSION",
    "GLACIER",
    "GLACIER_CC",
    "GLACIER_ICE",
    "GROUNDWATER",
    "LAKE_STORAGE",
    "MULTIPLE",
    "PERMAFROST_DEPTH",
    "PONDED_WATER",
    "ROOT",
    "SNOW",
    "SNOW_AGE",
    "SNOW_ALBEDO",
    "SNOW_COVER",
    "SNOW_DEPTH",
    "SNOW_LIQ",
    "SNOW_TEMP",
    "SOIL",
    "SOIL[0]",
    "SOIL[1]",
    "SOIL[2]",
    "SOIL_TEMP",
    "SURFACE_WATER",
    "SURFACE_WATER_TEMP",
    "TOTAL_SWE",
    "TRUNK",
    "WETLAND",
]

LandUseParameters = Literal[
    "ABST_PERCENT",
    "AET_COEFF",
    "BF_LOSS_FRACTION",
    "B_EXP",
    "CC_DECAY_COEFF",
    "DD_AGGRADATION",
    "DD_MELT_TEMP",
    "DD_REFREEZE_TEMP",
    "DEP_K",
    "DEP_MAX",
    "DEP_MAX_FLOW",
    "DEP_N",
    "DEP_SEEP_K",
    "DEP_THRESHOLD",
    "FOREST_COVERAGE",
    "FOREST_PET_CORR",
    "FOREST_SPARSENESS",
    "GAMMA_SCALE",
    "GAMMA_SCALE2",
    "GAMMA_SHAPE",
    "GAMMA_SHAPE2",
    "GLAC_STORAGE_COEFF",
    "GR4J_X4",
    "HBV_GLACIER_AG",
    "HBV_GLACIER_KMIN",
    "HBV_MELT_ASP_CORR",
    "HBV_MELT_FOR_CORR",
    "HBV_MELT_GLACIER_CORR",
    "HMETS_RUNOFF_COEFF",
    "IMPERMEABLE_FRAC",
    "LAKE_PET_CORR",
    "LAKE_REL_COEFF",
    "MAX_DEP_AREA_FRAC",
    "MAX_MELT_FACTOR",
    "MAX_SAT_AREA_FRAC",
    "MELT_FACTOR",
    "MIN_MELT_FACTOR",
    "OW_PET_CORR",
    "PARTITION_COEFF",
    "PDMROF_B",
    "PONDED_EXP",
    "REFREEZE_EXP",
    "REFREEZE_FACTOR",
    "ROUGHNESS",
    "SCS_CN",
    "SCS_IA_FRACTION",
    "SNOW_PATCH_LIMIT",
    "STREAM_FRACTION",
    "UBC_ICEPT_FACTOR",
]

VegetationParameters = Literal[
    "ALBEDO",
    "ALBEDO_WET",
    "CAP_LAI_RATIO",
    "CHU_MATURITY",
    "DRIP_PROPORTION",
    "MAX_CAPACITY",
    "MAX_HEIGHT",
    "MAX_INTERCEPT_RATE",
    "MAX_LAI",
    "MAX_LEAF_COND",
    "MAX_ROOT_LENGTH",
    "MAX_SNOW_CAPACITY",
    "MIN_RESISTIVITY",
    "PET_VEG_CORR",
    "PSI_CRITICAL",
    "RAIN_ICEPT_FACT",
    "RAIN_ICEPT_PCT",
    "RELATIVE_HT",
    "RELATIVE_LAI",
    "ROOTRADIUS",
    "ROOT_EXTINCT",
    "SAI_HT_RATIO",
    "SNOCAP_LAI_RATIO",
    "SNOW_ICEPT_FACT",
    "SNOW_ICEPT_PCT",
    "STEMFLOW_FRAC",
    "SVF_EXTINCTION",
    "TFRAIN",
    "TFSNOW",
    "TRUNK_FRACTION",
    "VEG_DENS",
    "VEG_DIAM",
    "VEG_MBETA",
    "XYLEM_FRAC",
]


class AirPressureMethod(Enum):
    BASIC = "AIRPRESS_BASIC"  # Default
    CONST = "AIRPRESS_CONST"
    DATA = "AIRPRESS_DATA"
    UBC = "AIRPRESS_UBC"


class Calendar(Enum):
    ALL_LEAP = "ALL_LEAP"
    GREGORIAN = "GREGORIAN"
    JULIAN = "JULIAN"
    NOLEAP = "NOLEAP"
    PROLEPTIC_GREGORIAN = "PROLEPTIC_GREGORIAN"
    STANDARD = "STANDARD"
    _365_DAY = "365_DAY"
    _366_DAY = "366_DAY"


class CatchmentRoute(Enum):
    """:CatchmentRoute"""

    DELAYED_FIRST_ORDER = "ROUTE_DELAYED_FIRST_ORDER"
    DUMP = "ROUTE_DUMP"
    EXP = "ROUTE_EXPONENTIAL"
    EXPONENTIAL_UH = "EXPONENTIAL_UH"
    GAMMA = "ROUTE_GAMMA_CONVOLUTION"
    RESERVOIR = "ROUTE_RESERVOIR_SERIES"
    TRI = "ROUTE_TRI_CONVOLUTION"
    TRIANGULAR_UH = "TRIANGULAR_UH"
    TRI_CONVOLUTION = "TRI_CONVOLUTION"


class CloudCoverMethod(Enum):
    NONE = "CLOUDCOV_NONE"  # default
    DATA = "CLOUDCOV_DATA"  # gauge or gridded time series used
    UBC = "CLOUDCOV_UBC"


class EvaluationMetrics(Enum):
    ABSERR = "ABSERR"
    ABSERR_RUN = "ABSERR_RUN"
    ABSMAX = "ABSMAX"
    DIAG_SPEARMAN = "DIAG_SPEARMAN"
    FUZZY_NASH = "FUZZY_NASH"
    KGE_PRIME = "KGE_PRIME"
    KLING_GUPTA = "KLING_GUPTA"
    LOG_NASH = "LOG_NASH"
    NASH_SUTCLIFFE = "NASH_SUTCLIFFE"
    NSC = "NSC"
    PCT_BIAS = "PCT_BIAS"
    PDIFF = "PDIFF"
    RCOEFF = "RCOEFF"
    RMSE = "RMSE"
    TMVOL = "TMVOL"


evaluation_metrics_multiplier = dict(
    ABSERR=-1,
    ABSMAX=-1,
    DIAG_SPEARMAN=1,
    KLING_GUPTA=1,
    LOG_NASH=1,
    NASH_SUTCLIFFE=1,
    NSC=1,
    PCT_BIAS="Not Supported",
    PDIFF=-1,
    RCOEFF=-1,
    RMSE=-1,
    TMVOL=-1,
)


class Evaporation(Enum):
    CONSTANT = "PET_CONSTANT"
    DATA = "PET_DATA"
    FROMMONTHLY = "PET_FROMMONTHLY"
    HAMON_1961 = "PET_HAMON_1961"
    HARGREAVES = "PET_HARGREAVES"
    HARGREAVES_1985 = "PET_HARGREAVES_1985"
    MAKKINK_1957 = "PET_MAKKINK_1957"
    MOHYSE = "PET_MOHYSE"
    MONTHLY_FACTOR = "PET_MONTHLY_FACTOR"
    OUDIN = "PET_OUDIN"
    PENMAN_COMBINATION = "PET_PENMAN_COMBINATION"
    PENMAN_MONTEITH = "PET_PENMAN_MONTEITH"
    PRIESTLEY_TAYLOR = "PET_PRIESTLEY_TAYLOR"
    TURC_1961 = "PET_TURC_1961"
    VAP_DEFICIT = "PET_VAPDEFICIT"


class LWIncomingMethod(Enum):
    DATA = "LW_INC_DATA"
    DEFAULT = "LW_INC_DEFAULT"
    DINGMAN = "LW_INC_DINGMAN"
    SICART = "LW_INC_SICART"
    SKYVIEW = "LW_INC_SKYVIEW"


class Interpolation(Enum):
    AVERAGE_ALL = "INTERP_AVERAGE_ALL"
    FROM_FILE = "INTERP_FROM_FILE"
    INVERSE_DISTANCE = "INTERP_INVERSE_DISTANCE"
    NEAREST_NEIGHBOR = "INTERP_NEAREST_NEIGHBOR"


class LWRadiationMethod(Enum):
    DATA = "LW_RAD_DATA"
    DEFAULT = "LW_RAD_DEFAULT"
    UBCWM = "LW_RAD_UBC"


class MonthlyInterpolationMethod(Enum):
    LINEAR_21 = "MONTHINT_LINEAR_21"
    LINEAR_FOM = "MONTHINT_LINEAR_FOM"
    LINEAR_MID = "MONTHINT_LINEAR_MID"
    UNIFORM = "MONTHINT_UNIFORM"


class OroPETCorrect(Enum):
    HBV = "OROCORR_HBV"
    NONE = "OROCORR_NONE"
    SIMPLELAPSE = "OROCORR_SIMPLELAPSE"


class OroPrecipCorrect(Enum):
    HBV = "OROCORR_HBV"
    NONE = "OROCORR_NONE"
    SIMPLELAPSE = "OROCORR_SIMPLELAPSE"
    UBC = "OROCORR_UBC"


class OroTempCorrect(Enum):
    HBV = "OROCORR_HBV"
    NONE = "OROCORR_NONE"
    SIMPLELAPSE = "OROCORR_SIMPLELAPSE"
    UBC = "OROCORR_UBC"
    UBC2 = "OROCORR_UBC_2"


class PotentialMeltMethod(Enum):
    """:PotentialMelt algorithms"""

    DATA = "POTMELT_DATA"
    DEGREE_DAY = "POTMELT_DEGREE_DAY"
    EB = "POTMELT_EB"
    HBV = "POTMELT_HBV"
    HMETS = "POTMELT_HMETS"
    NONE = "POTMELT_NONE"
    RESTRICTED = "POTMELT_RESTRICTED"
    UBC = "POTMELT_UBC"
    USACE = "POTMELT_USACE"


class Precipitation(Enum):
    DEFAULT = "PRECIP_RAVEN"


class PrecipIceptFract(Enum):
    USER = "PRECIP_ICEPT_USER"  # default
    EXPLAI = "PRECIP_ICEPT_EXPLAI"
    HEDSTROM = "PRECIP_ICEPT_HEDSTROM"
    LAI = "PRECIP_ICEPT_LAI"
    NONE = "PRECIP_ICEPT_NONE"


class RainSnowFraction(Enum):
    DATA = "RAINSNOW_DATA"
    DINGMAN = "RAINSNOW_DINGMAN"
    HARDER = "RAINSNOW_HARDER"
    HBV = "RAINSNOW_HBV"
    HSPF = "RAINSNOW_HSPF"
    SNTHERM89 = "RAINSNOW_SNTHERM89"
    UBC = "RAINSNOW_UBC"
    WANG = "RAINSNOW_WANG"


class RechargeMethod(Enum):
    DATA = "RECHARGE_DATA"
    NONE = "RECHARGE_NONE"


class RelativeHumidityMethod(Enum):
    CONSTANT = "RELHUM_CONSTANT"
    CORR = "RELHUM_CORR"
    DATA = "RELHUM_DATA"
    MINDEWPT = "RELHUM_MINDEWPT"
    WINDVEL = "WINDVEL_CORR"


class Routing(Enum):
    DIFFUSIVE_WAVE = "ROUTE_DIFFUSIVE_WAVE"
    HYDROLOGIC = "ROUTE_HYDROLOGIC"
    MUSKINGUM = "MUSKINGUM"
    NONE = "ROUTE_NONE"
    PLUG_FLOW = "ROUTE_PLUG_FLOW"
    STORAGE_COEFF = "ROUTE_STORAGE_COEFF"


class SoilModel(Enum):
    ONE_LAYER = "SOIL_ONE_LAYER"
    TWO_LAYER = "SOIL_TWO_LAYER"
    MULTILAYER = "SOIL_MULTILAYER"


SubBasinProperties = Literal[
    "CELERITY",
    "DIFFUSIVITY",
    "GAMMA_SCALE",
    "GAMMA_SHAPE",
    "MANNINGS_N",
    "NUM_RESERVOIRS",
    "Q_REFERENCE",
    "RAIN_CORR",
    "RES_CONSTANT",
    "SLOPE",
    "SNOW_CORR",
    "TIME_CONC",
    "TIME_LAG",
    "TIME_TO_PEAK",
]


class SubdailyMethod(Enum):
    NONE = "SUBDAILY_NONE"
    SIMPLE = "SUBDAILY_SIMPLE"
    UBC = "SUBDAILY_UBC"


class SWCanopyCorrect(Enum):
    NONE = "SW_CANOPY_CORR_NONE"  # Default
    DYNAMIC = "SW_CANOPY_CORR_DYNAMIC"
    STATIC = "SW_CANOPY_CORR_STATIC"
    UBC = "SW_CANOPY_CORR_UBC"


class SWCloudCorrect(Enum):
    NONE = "SW_CLOUD_CORR_NONE"  # Default
    ANNANDALE = "SW_CLOUD_CORR_ANNANDALE"
    DINGMAN = "SW_CLOUD_CORR_DINGMAN"
    UBC = "SW_CLOUD_CORR_UBCWM"


class SWRadiationMethod(Enum):
    DATA = "SW_RAD_DATA"
    DEFAULT = "SW_RAD_DEFAULT"
    UBCWM = "SW_RAD_UBCWM"


class WindspeedMethod(Enum):
    CONSTANT = "WINDVEL_CONSTANT"
    DATA = "WINDVEL_DATA"
    UBC = "WINDVEL_UBC"


class EnKFMode(Enum):
    CLOSED_LOOP = "ENKF_CLOSED_LOOP"
    FORECAST = "ENKF_FORECAST"
    OPEN_FORECAST = "ENKF_OPEN_FORECAST"
    OPEN_LOOP = "ENKF_OPEN_LOOP"
    SPINUP = "ENKF_SPINUP"
