package cn.reghao.bnt.web.admin.model.po;

import cn.reghao.bnt.web.admin.model.constant.MenuType;
import cn.reghao.bnt.web.util.BaseEntity;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import java.util.Map;
import java.util.Set;

/**
 * Layui 菜单, 作为 RBAC 中的 resource
 *
 * @author reghao
 * @date 2021-04-04 22:42:14
 */
@Setter
@Getter
@Table(name = "rbac_menu")
@Entity
public class Menu extends BaseEntity {
    @NotBlank(message = "菜单类型不能为空白字符串")
    private String type;
    // 后台侧边栏显示的名字
    @NotBlank(message = "菜单名不能为空白字符串")
    private String name;
    // Menu 管理页面显示的名字
    private String menuName;
    @Pattern(regexp = "[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]", message = "url 格式不正确")
    @Length(min = 1, max = 128, message = "域名长度应小于 128 个字符")
    private String url;
    private String icon;
    // 父级菜单 ID
    @NotNull(message = "父级菜单不能为 NULL")
    private Integer pid;
    // 在同一个 pid 组内的位置，作为排序使用
    private Integer pos;
    // 是否在侧边栏显示菜单
    @NotNull
    @Column(nullable = false)
    private Boolean visible;
    // Menu 拥有的所有子 Menu(按排序顺序, 不持久化)
    @Transient
    private Map<Integer, Menu> children;
    @ManyToMany(mappedBy = "menus")
    private Set<Role> roles;

    public Menu() {
        this.icon = "fa fa-cog";
        this.visible = true;
    }

    public Menu(MenuType menuType, boolean visible, String name, String url, int pid) {
        this.type = menuType.name();
        this.name = name;
        this.menuName = name;
        this.url = url;
        this.icon = "fa fa-cog";
        this.pid = pid;
        this.pos = 1;
        this.visible = visible;
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = result * 31 + type.hashCode();
        result = result * 31 + url.hashCode();
        return result;
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }

        if (other instanceof Menu) {
            Menu o = (Menu) other;
            return o.type.equals(type) && o.url.equals(url);
        } else {
            return false;
        }
    }
}
