from typing import Callable, Dict, List, Optional, Any
from copy import deepcopy

class ModuleInfo:
    def __init__(self, name: str, meta_class: Callable, 
                fixed_params: Dict = {}, unknown_params: Optional[Dict] = None):
        self.name = name
        self.meta_class = meta_class
        self.fixed_params = fixed_params
        self.unknown_params = unknown_params
    
    def is_undetermined(self) -> bool:
        if self.unknown_params is None:
            return False
        else:
            return True
    
    def set_unknown_params(self, name: str, value: Any):
        self.unknown_params[name] = value
    
    def get_instance(self):
        _params = deepcopy(self.fixed_params)
        if self.unknown_params is not None:
            _params.update(self.unknown_params)
        return self.meta_class(**_params)
    
    def __repr__(self) -> str:
        return f"name={self.name}, meta_class={self.meta_class}, fixed_params={self.fixed_params}, unknown_params={self.unknown_params}"

class ModelInfo:
    def __init__(self, module_list: List[ModuleInfo]):
        self.module_list = module_list
    
    def __iter__(self):
        for module_info in self.module_list:
            yield module_info