using System;
using System.Collections.Generic;

namespace VCommon.VApplication.Authorization
{
    public class PermissionNode
    {
        private readonly PermissionTree _tree;
        private readonly List<PermissionNode> _children = new List<PermissionNode>();

        /// <summary>
        /// 权限代码, 产品内唯一
        /// </summary>
        public string Code { get; }

        /// <summary>
        /// 面向用户的显示名称
        /// </summary>
        public string Name { get; }

        /// <summary>
        /// 面向用户的描述
        /// </summary>
        public string Description { get; }

        /// <summary>
        /// 面向运营商（平台）的显示名称
        /// </summary>
        public string NameForOperator { get; }

        /// <summary>
        /// 面向运营商（平台）的描述
        /// </summary>
        public string DescriptionForOperator { get; }

        public MultiTenancySides TenancySide { get; }

        public IReadOnlyList<PermissionNode> Children => _children;

        public object CustomData { get; set; }

        internal PermissionNode(PermissionTree tree, string code, string name, string description, string nameForOperator, string descriptionForOperator, MultiTenancySides side = MultiTenancySides.Both, object customData = null)
        {
            _tree = tree;
            Code = code;
            Name = name;
            Description = description;
            NameForOperator = nameForOperator;
            DescriptionForOperator = descriptionForOperator;
            TenancySide = side;
            CustomData = customData;
        }

        public PermissionNode CreateChildNode(string code, string name, string description = null, string nameForOperator = null, string descriptionForOperator = null, MultiTenancySides side = MultiTenancySides.Both, object customData = null)
        {
            if (_tree.CodeHashSet.Contains(code)) throw new ArgumentException($"重复的权限代码:{code},名称:{name}");

            var node = new PermissionNode(_tree, code, name, description, nameForOperator, descriptionForOperator, side, customData);
            _children.Add(node);
            _tree._allNode.Add(node);
            _tree.CodeHashSet.Add(code);
            return node;
        }

        public void Traverse(Action<PermissionNode> visitor)
        {
            visitor(this);
            foreach (var child in Children) child.Traverse(visitor);
        }
    }
}
