package com.zb.mom.ww.mxgateway.client;

import java.util.Collections;
import java.util.List;

/**
 * Filters and shape options for {@link GalaxyRepositoryClient#browse(BrowseChildrenOptions)}.
 * Mirror of the existing DiscoverHierarchy options for the lazy-browse path.
 *
 * <p>All filter fields are AND-combined server-side. Empty / unset fields disable
 * that filter. The {@code includeAttributes} tri-state uses {@code null} to mean
 * "let the server use its default"; non-{@code null} forwards the explicit flag.
 */
public final class BrowseChildrenOptions {
    private final List<Integer> categoryIds;
    private final List<String> templateChainContains;
    private final String tagNameGlob;
    private final Boolean includeAttributes;
    private final boolean alarmBearingOnly;
    private final boolean historizedOnly;

    private BrowseChildrenOptions(Builder b) {
        this.categoryIds = List.copyOf(b.categoryIds);
        this.templateChainContains = List.copyOf(b.templateChainContains);
        this.tagNameGlob = b.tagNameGlob;
        this.includeAttributes = b.includeAttributes;
        this.alarmBearingOnly = b.alarmBearingOnly;
        this.historizedOnly = b.historizedOnly;
    }

    /** @return immutable list of category IDs to include; empty disables this filter. */
    public List<Integer> getCategoryIds() { return categoryIds; }

    /** @return immutable list of template names that must appear in each child's template chain. */
    public List<String> getTemplateChainContains() { return templateChainContains; }

    /** @return SQL-LIKE-style glob applied to {@code tag_name}; empty disables. */
    public String getTagNameGlob() { return tagNameGlob; }

    /** @return tri-state override for {@code include_attributes}; {@code null} keeps the server default. */
    public Boolean getIncludeAttributes() { return includeAttributes; }

    /** @return restrict to alarm-bearing objects. */
    public boolean isAlarmBearingOnly() { return alarmBearingOnly; }

    /** @return restrict to objects with at least one historized attribute. */
    public boolean isHistorizedOnly() { return historizedOnly; }

    /** @return a fresh builder. */
    public static Builder builder() { return new Builder(); }

    /** @return options with every filter disabled and {@code includeAttributes} unset. */
    public static BrowseChildrenOptions empty() { return builder().build(); }

    /** Fluent builder for {@link BrowseChildrenOptions}. */
    public static final class Builder {
        private List<Integer> categoryIds = Collections.emptyList();
        private List<String> templateChainContains = Collections.emptyList();
        private String tagNameGlob = "";
        private Boolean includeAttributes = null;
        private boolean alarmBearingOnly = false;
        private boolean historizedOnly = false;

        /** Sets the category-id filter. */
        public Builder categoryIds(List<Integer> v) {
            this.categoryIds = v == null ? Collections.emptyList() : v;
            return this;
        }

        /** Sets the template-chain-contains filter. */
        public Builder templateChainContains(List<String> v) {
            this.templateChainContains = v == null ? Collections.emptyList() : v;
            return this;
        }

        /** Sets the tag-name glob. */
        public Builder tagNameGlob(String v) {
            this.tagNameGlob = v == null ? "" : v;
            return this;
        }

        /** Sets the tri-state {@code includeAttributes} override; {@code null} keeps the server default. */
        public Builder includeAttributes(Boolean v) {
            this.includeAttributes = v;
            return this;
        }

        /** Toggles the alarm-bearing-only filter. */
        public Builder alarmBearingOnly(boolean v) {
            this.alarmBearingOnly = v;
            return this;
        }

        /** Toggles the historized-only filter. */
        public Builder historizedOnly(boolean v) {
            this.historizedOnly = v;
            return this;
        }

        /** Builds the immutable options. */
        public BrowseChildrenOptions build() {
            return new BrowseChildrenOptions(this);
        }
    }
}
