# -*- coding: utf-8 -*-
"""
CleanTreeTool · 输入端自动改名版
- 输入端 Tree：连接别的组件后，显示名称改成对方输出端名
- 输出端 Tree_Cleaned：名字固定，用来输出清理后的树
"""

import Grasshopper as gh
from Grasshopper import DataTree
from Grasshopper.Kernel.Data import GH_Path
import Grasshopper.Kernel.Types as ght


class CleanTreeTool(object):

    @staticmethod
    def is_null_or_invalid(x):
        """判断是否为 Null / Invalid / 空对象"""
        if x is None:
            return True

        if isinstance(x, str) and x == "":
            return True

        if isinstance(x, (list, tuple)) and len(x) == 0:
            return True

        if isinstance(x, ght.IGH_Goo):
            try:
                if getattr(x, "IsNull", False):
                    return True
                if not getattr(x, "IsValid", True):
                    return True
            except:
                pass

            try:
                v = x.Value
                if hasattr(v, "IsValid") and (not v.IsValid):
                    return True
            except:
                pass

            return False

        if hasattr(x, "IsValid"):
            try:
                if x.IsValid is False:
                    return True
            except:
                pass

        return False

    @staticmethod
    def clean(tree_in):
        """对 DataTree 做 Clean Tree：删 Null/Invalid/Empty 分支"""
        if tree_in is None:
            return None

        # 只对 DataTree 进行处理，其它类型直接返回
        if not isinstance(tree_in, DataTree[object]):
            return tree_in

        new_tree = DataTree[object]()

        for path in tree_in.Paths:
            try:
                branch = list(tree_in.Branch(path))
            except:
                branch = []

            valid_items = [
                v for v in branch
                if not CleanTreeTool.is_null_or_invalid(v)
            ]

            if not valid_items:
                continue

            for v in valid_items:
                new_tree.Add(v, path)

        return new_tree


def sync_io_names(component):
    """
    1. 输入端 Tree：NickName 改成其来源端口的名字
    2. 输出端 Tree_Cleaned：NickName 固定保持为 'Tree_Cleaned'
    （不修改任何端口的 Name，只改 NickName）
    """
    # 输入端
    if component.Params.Input.Count > 0:
        in_param = component.Params.Input[0]
        if in_param.Sources.Count > 0:
            src = in_param.Sources[0]
            src_name = src.NickName or src.Name or "Tree"
        else:
            src_name = "Tree"
        in_param.NickName = src_name

    # 输出端
    if component.Params.Output.Count > 0:
        out_param = component.Params.Output[0]
        out_param.NickName = "Tree_Cleaned"   # 显示名固定

if __name__ == '__main__':
    # ========== 主逻辑 ==========

    # 先同步端口显示名
    sync_io_names(ghenv.Component)

    # 再做数据清理并输出
    if Tree is None:
        Tree_Cleaned = None
    else:
        Tree_Cleaned = CleanTreeTool.clean(Tree)
