package net.knarcraft.permissionsigns.container; import net.knarcraft.permissionsigns.formatting.StringFormatter; import net.knarcraft.permissionsigns.formatting.TranslatableMessage; import net.knarcraft.permissionsigns.formatting.Translator; import net.knarcraft.permissionsigns.manager.EconomyManager; import org.bukkit.Location; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import static net.knarcraft.permissionsigns.formatting.StringFormatter.replacePlaceholder; /** * This class represents a placed and active permission sign */ public class PermissionSign { private Location signLocation; private final String name; private final List permissionNodes; private final int duration; private final double cost; private static Map timeUnits; private static List sortedUnits; /** * Instantiates a new permission sign * * @param signLocation

The location of the permission sing in the world

* @param name

The name to display on the permission sign

* @param permissionNodes

The permissions granted when this permission sign is used

* @param duration

The duration, in seconds, until the permission should be revoked. 0 for non-temporary

* @param cost

The cost of using this permission sign

*/ public PermissionSign(Location signLocation, String name, List permissionNodes, int duration, double cost) { this.signLocation = signLocation; this.name = name; this.permissionNodes = new ArrayList<>(permissionNodes); //Automatically fix negative values this.duration = Math.max(0, duration); this.cost = Math.max(0, cost); } /** * Instantiates a new permission sign * * @param name

The name to display on the permission sign

* @param permissionNodes

The permissions granted when this permission sign is used

* @param duration

The duration, in seconds, until the permission should be revoked. 0 for non-temporary

* @param cost

The cost of using this permission sign

*/ public PermissionSign(String name, List permissionNodes, int duration, double cost) { this.name = name; this.permissionNodes = new ArrayList<>(permissionNodes); this.duration = Math.max(0, duration); this.cost = Math.max(0, cost); } /** * Sets the sign location of this permission sign * * @param signLocation

>The location of this permission sign's actual sign

*/ public void setSignLocation(Location signLocation) { if (this.signLocation == null) { this.signLocation = signLocation; } else { throw new IllegalArgumentException("A sign location cannot be overwritten"); } } /** * Gets the location of this permission sign * *

The location might be null until a sign has been right-clicked

* * @return

The location of this permission sign

*/ public Location getSignLocation() { return signLocation; } /** * Gets the name of this permission sign * * @return

The name of this permission sign

*/ public String getName() { return name; } /** * Gets the permissions nodes granted by this permission sign * * @return

The permission nodes granted by this permission sign

*/ public List getPermissionNodes() { return new ArrayList<>(this.permissionNodes); } /** * Gets the duration the permissions should last before expiring * *

A duration of 0 will give a permanent permission.

* * @return

The duration of the permissions

*/ public int getDuration() { return this.duration; } /** * Gets the cost of using this permissions sign * * @return

The cost of using this permission sign

*/ public double getCost() { return this.cost; } /** * Gets the lines used to represent this permission sign on a sign * * @return

The lines used to draw this permission sign

*/ public String[] getSignLines() { String[] lines = new String[4]; lines[0] = Translator.getTranslatedMessage(TranslatableMessage.SIGN_PREFIX); lines[1] = replacePlaceholder(Translator.getTranslatedMessage( TranslatableMessage.SIGN_NAME_FORMAT), "{name}", getName()); lines[2] = getDurationString(); lines[3] = getCostString(); return lines; } @Override public boolean equals(Object other) { if (!(other instanceof PermissionSign)) { return false; } if (this == other) { return true; } return this.signLocation.equals(((PermissionSign) other).signLocation); } /** * Gets the string used for displaying this sign's duration * * @return

The string used for displaying this sign's duration

*/ public String getDurationString() { if (duration == 0) { return Translator.getTranslatedMessage(TranslatableMessage.SIGN_PERMANENT); } else { if (sortedUnits == null) { initializeUnits(); } for (Double unit : sortedUnits) { if (duration / unit >= 1) { double units = round(duration / unit); return formatDurationString(units, timeUnits.get(unit)[units == 1 ? 0 : 1], (units * 10) % 10 == 0); } } return formatDurationString(duration, TranslatableMessage.UNIT_SECONDS, false); } } /** * Gets the string used for displaying this sign's cost * * @return

The string used for displaying this sign's cost

*/ public String getCostString() { if (cost == 0) { return Translator.getTranslatedMessage(TranslatableMessage.SIGN_COST_FREE); } else { String currency = EconomyManager.getCurrency(cost != 1); String format = Translator.getTranslatedMessage(TranslatableMessage.SIGN_COST_FORMAT); String formatted = StringFormatter.replacePlaceholders(format, new String[]{"{cost}", "{currency}"}, new String[]{"%.2f", currency}); return String.format(formatted, cost); } } /** * Rounds a number to its last two digits * * @param number

The number to round

* @return

The rounded number

*/ private double round(double number) { return Math.round(number * 100.0) / 100.0; } /** * Formats a duration string * * @param duration

The duration to display

* @param translatableMessage

The time unit to display

* @param castToInt

Whether to cast the duration to an int

* @return

The formatted duration string

*/ private String formatDurationString(double duration, TranslatableMessage translatableMessage, boolean castToInt) { String durationFormat = Translator.getTranslatedMessage(TranslatableMessage.SIGN_DURATION_FORMAT); durationFormat = replacePlaceholder(durationFormat, "{unit}", Translator.getTranslatedMessage(translatableMessage)); return replacePlaceholder(durationFormat, "{duration}", castToInt ? String.valueOf((int) duration) : String.valueOf(duration)); } /** * Initializes the mapping of available time units for formatting permission sign duration */ private static void initializeUnits() { double minute = 60; double hour = minute * 60; double day = hour * 24; timeUnits = new HashMap<>(); timeUnits.put(day, new TranslatableMessage[]{TranslatableMessage.UNIT_DAY, TranslatableMessage.UNIT_DAYS}); timeUnits.put(hour, new TranslatableMessage[]{TranslatableMessage.UNIT_HOUR, TranslatableMessage.UNIT_HOURS}); timeUnits.put(minute, new TranslatableMessage[]{TranslatableMessage.UNIT_MINUTE, TranslatableMessage.UNIT_MINUTES}); timeUnits.put(1D, new TranslatableMessage[]{TranslatableMessage.UNIT_SECOND, TranslatableMessage.UNIT_SECONDS}); sortedUnits = new ArrayList<>(timeUnits.keySet()); Collections.sort(sortedUnits); Collections.reverse(sortedUnits); } }