from pydantic import BaseModel
from typing import Dict, List, AnyStr

from models.target import Target


class ObjectiveFunction(BaseModel):
    # minimizing tif/tcc target value is only option currently
    # as we add more we can build this out to be more dynamic
    # likely with models representing each objective function type
    tif_targets: List[Target]
    tcc_targets: List[Target]
    target_variance_percentage: int = 10
    objective: AnyStr = "minimize"
    weight: Dict = {'tif': 1, 'tcc': 1}

    def increment_targets_drift(self,
                                limit: float or bool,
                                all: bool = False,
                                amount: float = 0.1,
                                targets: list[Target] = []) -> bool:
        if all:
            for target in self.tif_targets:
                target.drift = round(target.drift + amount, 2)
            for target in self.tcc_targets:
                target.drift = round(target.drift + amount, 2)
        else:
            for target in targets:
                target.drift = round(target.drift + amount, 2)
        return amount

    def update_targets_drift(self, amount: float = 0.0):
        for target in self.tif_targets:
            target.drift = round(amount, 2)
        for target in self.tcc_targets:
            target.drift = round(amount, 2)

    def minimum_drift(self) -> float:
        minimum_drift = 0.0

        for target in self.all_targets():
            if target.drift < minimum_drift:
                minimum_drift = target.drift

        return minimum_drift

    def all_targets(self) -> list[Target]:
        return self.tif_targets + self.tcc_targets