001/*
002 * PermissionsEx
003 * Copyright (C) zml and PermissionsEx contributors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package ca.stellardrift.permissionsex.rank;
018
019import ca.stellardrift.permissionsex.context.ContextValue;
020import ca.stellardrift.permissionsex.subject.ImmutableSubjectData;
021import ca.stellardrift.permissionsex.subject.SubjectRef;
022import net.kyori.adventure.text.ComponentLike;
023
024import java.util.List;
025import java.util.Map;
026import java.util.Set;
027
028/**
029 * Represents a track of ranks along which a user can be promoted or demoted.
030 *
031 * <p>These objects are immutable.</p>
032 *
033 * @since 2.0.0
034 */
035public interface RankLadder extends ComponentLike {
036
037    /**
038     * The name assigned to the rank-ladder.
039     *
040     * <p>These names are case-insensitive.</p>
041     *
042     * @return The ladder's name
043     * @since 2.0.0
044     */
045    String name();
046
047    /**
048     * Promote the given subject data on this rank ladder in the given context.
049     *
050     * If the subject is not currently on the rank ladder in this context, the subject will be placed on the lowest rank in this ladder.
051     * If the subject is currently at the top of this rank ladder, nothing will happen.
052     * If the subject has multiple memberships at various points in this rank ladder, all of them will be moved up by one step
053     *
054     * @param contexts The context combination to promote in
055     * @param input The subject data to promote
056     * @return The promoted data
057     * @since 2.0.0
058     */
059    ImmutableSubjectData promote(Set<ContextValue<?>> contexts, ImmutableSubjectData input);
060
061    /**
062     * Demote the given subject data on this rank ladder in the given context.
063     *
064     * <p>If the subject is not currently on the rank ladder in this context, nothing will happen.
065     * If the subject is currently at the bottom of this rank ladder, the subject will be removed
066     * from the rank ladder entirely. If the subject has multiple memberships at various points in
067     * this rank ladder, all of them will be moved down by one step</p>
068     *
069     * @param contexts The context combination to promote in
070     * @param input The subject data to promote
071     * @return the demoted data
072     * @since 2.0.0
073     */
074    ImmutableSubjectData demote(Set<ContextValue<?>> contexts, ImmutableSubjectData input);
075
076    /**
077     * Return if this subject is a member of any subjects that are part of this rank ladder within
078     * the given contexts.
079     *
080     * @param contexts The contexts to check in
081     * @param subject The subject
082     * @return Whether this ladder contains any of the direct parents of the subject in the given contexts
083     * @since 2.0.0
084     */
085    boolean isOnLadder(Set<ContextValue<?>> contexts, ImmutableSubjectData subject);
086
087    /**
088     * Return a new rank ladder with the specified rank added at the highest point in the ladder.
089     *
090     * <p>If the rank is currently already in the rank ladder, it will be moved to the
091     * highest point.</p>
092     *
093     * @param subject the rank to add
094     * @return a rank ladder instance with the appropriate changes
095     * @since 2.0.0
096     */
097    RankLadder with(SubjectRef<?> subject);
098
099
100    /**
101     * Return a new rank ladder with the specified rank added at a given point in the rank ladder.
102     * If the rank is currently already in the rank ladder, it will be moved to the given index.
103     *
104     * @param subject The rank to add
105     * @param index The point to add the rank at. Must be on the range [0, getRanks().size()]
106     * @return a rank ladder instance with the appropriate changes
107     */
108    RankLadder with(SubjectRef<?> subject, int index);
109
110    /**
111     * Get the index of this rank in the current ladder. This index is the index of the rank in {@link #ranks()}.
112     *
113     * @param subject The rank to find the index of
114     * @return The index of the rank, or -1 if the rank is not present.
115     */
116    int indexOf(SubjectRef<?> subject);
117
118    /**
119     * Remove the given rank from this rank ladder.
120     *
121     * @param subject The rank to remove
122     * @return A new ladder without the given rank, or this if the rank was not contained in this ladder
123     */
124    RankLadder without(SubjectRef<?> subject);
125
126    /**
127     * Provides a way to iterate through ranks currently active in this ladder.
128     * @return A list of ranks present in the ladder. This list is immutable.
129     */
130    List<? extends SubjectRef<?>> ranks();
131
132}