#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
@Project: pyufim3.0
@Author: shi yao <euler_shiyao@foxmail.com>
@Create Time: 2025-11-24 星期一 16:21:45
python version: python 
"""


from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Dict, Optional, Callable

# 插件注册表（name -> plugin class）
_PLUGIN_REGISTRY: Dict[str, type] = {}


def register_plugin(name: str):
    """装饰器：注册插件"""
    def deco(cls):
        _PLUGIN_REGISTRY[name] = cls
        cls.name = name
        return cls
    return deco


def get_plugin(name: str):
    if name not in _PLUGIN_REGISTRY:
        raise KeyError(f"Plugin '{name}' not registered. Available: {list(_PLUGIN_REGISTRY)}")
    return _PLUGIN_REGISTRY[name]


@dataclass
class UFIMProject:
    """
    共用对象：所有数据路径、结果、模块状态都放这里
    后续你可以把真正的 DEM/landuse 读取后的 ndarray 也挂进来
    """
    # 数据路径/对象（可选）
    data: Dict[str, Any] = field(default_factory=dict)

    # 结果路径/对象
    results: Dict[str, Any] = field(default_factory=dict)

    # 已启用插件实例
    plugins: Dict[str, Any] = field(default_factory=dict)

    # 你可以放全局配置、网格信息、坐标系等
    config: Dict[str, Any] = field(default_factory=dict)

    # ---------------- 数据相关 ----------------
    def add_data(self, key: str, value: Any):
        self.data[key] = value
        return self

    def get_data(self, key: str, default=None):
        return self.data.get(key, default)

    def has_data(self, key: str) -> bool:
        return key in self.data

    # ---------------- 插件相关 ----------------
    def use(self, plugin_name: str, **kwargs) -> "UFIMProject":
        """
        启用一个可选模块
        - 会实例化插件
        - 插件 attach(self) 可往 self 上挂属性/方法/参数
        """
        plugin_cls = get_plugin(plugin_name)
        plugin = plugin_cls(**kwargs)
        plugin.attach(self)     # 给project附属性
        self.plugins[plugin_name] = plugin
        return self

    def run_plugin(self, plugin_name: str, **kwargs):
        if plugin_name not in self.plugins:
            raise RuntimeError(f"Plugin '{plugin_name}' not enabled. Call project.use('{plugin_name}') first.")
        return self.plugins[plugin_name].run(self, **kwargs)

    # ---------------- 主模型 ----------------
    def run(self, **kwargs):
        """
        运行主模型。现在先 print
        """
        from .model import run_main_model
        out = run_main_model(self, **kwargs)
        self.results["main"] = out
        return out
