package joshie.harvest.plugins.crafttweaker.handlers;
import joshie.harvest.api.calendar.Weekday;
import joshie.harvest.api.npc.IInfoButton;
import joshie.harvest.api.npc.NPC;
import joshie.harvest.api.shops.IPurchasable;
import joshie.harvest.api.shops.IRequirement;
import joshie.harvest.api.shops.Shop;
import joshie.harvest.plugins.crafttweaker.CraftTweaker;
import joshie.harvest.plugins.crafttweaker.base.BaseUndoable;
import joshie.harvest.plugins.crafttweaker.wrappers.GreetingShopWrapper;
import joshie.harvest.plugins.crafttweaker.wrappers.PurchasableWrapper;
import joshie.harvest.plugins.crafttweaker.wrappers.PurchasableWrapperMaterials;
import joshie.harvest.shops.HFShops;
import joshie.harvest.shops.purchasable.Purchasable;
import joshie.harvest.shops.purchasable.PurchasableMaterials;
import minetweaker.MineTweakerAPI;
import minetweaker.api.item.IIngredient;
import minetweaker.api.item.IItemStack;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import stanhebben.zenscript.annotations.Optional;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import javax.annotation.Nullable;
import java.util.Locale;
import static joshie.harvest.core.lib.HFModInfo.MODID;
import static joshie.harvest.plugins.crafttweaker.CraftTweaker.asStack;
@ZenClass("mods.harvestfestival.Shops")
public class Shops {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////Creating Shops//////////////////////////////////////////////////////////////////////////////////////////////////// ///////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ZenMethod
@SuppressWarnings("unused")
public static void addShopToNPC(String npc, String shop, String greeting, String openinghours, @Optional String hoursText) {
NPC theNPC = NPC.REGISTRY.get(new ResourceLocation(MODID, npc));
if (theNPC == null) CraftTweaker.logError(String.format("No NPC with the id %s could be found. Use /hf npclist for a list of ids", npc));
else if (theNPC.isShopkeeper()) CraftTweaker.logError(String.format("Attempted to add a shop to %s when they already have a shop", theNPC.getLocalizedName()));
else if (Shop.REGISTRY.containsKey(new ResourceLocation("MineTweaker3", shop.toLowerCase()))) CraftTweaker.logError(String.format("Attempted to add a shop with a duplicate id: %s", "MineTweaker3:" + shop.toLowerCase()));
else MineTweakerAPI.apply(new AddShop(theNPC, shop, greeting, openinghours, hoursText));
}
private static class AddShop extends BaseUndoable {
private final ResourceLocation resource;
private final String name;
private final NPC npc;
private final String greeting;
private final String openinghours;
private IInfoButton hours;
private Shop shop;
AddShop(NPC npc, String shop, String greeting, String openinghours, @Nullable String hoursText) {
this.resource = new ResourceLocation("MineTweaker3", shop.toLowerCase());
this.name = shop;
this.npc = npc;
this.greeting = greeting;
this.openinghours = openinghours;
if (hoursText != null) this.hours = new GreetingShopWrapper(hoursText);
}
@Override
public String getDescription() {
return "Created the shop " + name;
}
private void processTimeString(String time) {
String[] split = time.split(",");
if (split.length == 3) {
Weekday day = Weekday.valueOf(split[0].toUpperCase(Locale.ENGLISH));
int start = Integer.parseInt(split[1]);
int end = Integer.parseInt(split[2]);
shop.addOpening(day, start, end);
}
}
@Override
public void apply() {
shop = new Shop(resource) {
@Override
public String getLocalizedName() {
return name;
}
@Override
public String getWelcome(NPC npc) {
return greeting;
}
};
npc.setShop(shop);
if (hours == null) npc.setHasInfo(null);
else npc.setHasInfo(hours);
Shop.REGISTRY.put(resource, shop);
String[] hours = openinghours.replace(" ", "").split(";");
for (String time: hours) processTimeString(time);
}
@Override
public boolean canUndo() {
return shop != null;
}
@Override
public void undo() {
npc.setShop(null);
npc.setHasInfo(null);
Shop.REGISTRY.remove(resource);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////Adding Items////////////////////////////////////////////////////////////////////////////////////////////////////// ///////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ZenMethod
@SuppressWarnings("unused")
public static void addPurchasable(String shop, IItemStack sellable, long cost, @Optional IIngredient[] materials) {
Shop theShop = Shop.REGISTRY.get(new ResourceLocation(shop));
if (theShop == null) CraftTweaker.logError(String.format("No shop with the id %s could be found. Use /hf shoplist for a list of ids", shop));
MineTweakerAPI.apply(new AddPurchasable(theShop, asStack(sellable), cost, CraftTweaker.asRequirements(materials)));
}
private static class AddPurchasable extends BaseUndoable {
protected final Shop shop;
protected final ItemStack stack;
protected final long cost;
protected final IRequirement[] required;
protected IPurchasable purchasable;
AddPurchasable(Shop shop, ItemStack stack, long cost, @Nullable IRequirement[] stacks) {
this.shop = shop;
this.stack = stack;
this.cost = cost;
this.required = stacks;
}
@Override
public String getDescription() {
return "Adding " + stack.getDisplayName() + " to " + shop.getLocalizedName();
}
@Override
public void apply() {
purchasable = required != null ? purchasable = new PurchasableMaterials(cost, stack, required) : new Purchasable(cost, stack);
shop.addItem(purchasable);
}
@Override
public boolean canUndo() {
return purchasable != null;
}
@Override
public void undo() {
shop.removeItem(purchasable);
}
}
@ZenMethod
@SuppressWarnings("unused, deprecation")
@Deprecated //TODO: Remove in 0.7+
public static void addPurchasableToBuilder(IItemStack sellable, int wood, int stone, long cost) {
MineTweakerAPI.apply(new AddBuilderPurchasable(asStack(sellable), wood, stone, cost));
}
@Deprecated //TODO: Remove in 0.7+
private static class AddBuilderPurchasable extends AddPurchasable {
protected final int stone;
protected final int wood;
AddBuilderPurchasable(ItemStack stack, int stone, int wood, long cost) {
super(HFShops.CARPENTER, stack, cost, null);
this.stone = stone;
this.wood = wood;
}
@Override
public void apply() {
purchasable = new PurchasableMaterials(cost, stone, wood, stack);
shop.addItem(purchasable);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////Removing Items//////////////////////////////////////////////////////////////////////////////////////////////////// ///////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ZenMethod
@SuppressWarnings("unused")
public static void removePurchasable(String shop, String input) {
Shop theShop = Shop.REGISTRY.get(new ResourceLocation(shop));
String id = fixPurchasableID(input);
if (theShop == null) CraftTweaker.logError(String.format("No shop with the id %s could be found. Use /hf shoplist for a list of ids", shop));
else if (theShop.getPurchasableFromID(id) == null) CraftTweaker.logError(String.format("No purchasable with the id %s could be found in " + theShop.getLocalizedName(), id));
else MineTweakerAPI.apply(new RemovePurchasable(theShop, theShop.getPurchasableFromID(id)));
}
private static class RemovePurchasable extends BaseUndoable {
protected final Shop shop;
protected final IPurchasable purchasable;
RemovePurchasable(Shop shop, IPurchasable purchasable) {
this.shop = shop;
this.purchasable = purchasable;
}
@Override
public String getDescription() {
return "Removing " + purchasable.getDisplayName() + " from " + shop.getLocalizedName();
}
@Override
public void apply() {
shop.removeItem(purchasable);
}
@Override
public void undo() {
shop.addItem(purchasable);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////Adjusting Items/////////////////////////////////////////////////////////////////////////////////////////////////// ///////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ZenMethod
@SuppressWarnings("unused")
public static void adjustPurchasable(String shop, String input, long cost, @Optional IItemStack[] materials) {
Shop theShop = Shop.REGISTRY.get(new ResourceLocation(shop));
String id = fixPurchasableID(input);
if (theShop == null) CraftTweaker.logError(String.format("No shop with the id %s could be found. Use /hf shoplist for a list of ids", shop));
else if (theShop.getPurchasableFromID(id) == null) CraftTweaker.logError(String.format("No purchasable with the id %s could be found in " + theShop.getLocalizedName(), id));
else MineTweakerAPI.apply(new AdjustPurchasable(theShop, theShop.getPurchasableFromID(id), cost, CraftTweaker.asRequirements(materials)));
}
private static class AdjustPurchasable extends BaseUndoable {
protected final Shop shop;
protected final IPurchasable purchasable;
protected final long cost;
private final IRequirement[] required;
IPurchasable wrapper;
@SuppressWarnings("unchecked")
AdjustPurchasable(Shop shop, IPurchasable purchasable, long cost, @Nullable IRequirement[] stacks) {
this.shop = shop;
this.purchasable = purchasable;
this.cost = cost;
this.required = stacks;
}
@Override
public String getDescription() {
return "Adjusting value of " + purchasable.getDisplayName();
}
@Override
@SuppressWarnings("unchecked")
public void apply() {
shop.removeItem(purchasable); //Remove the item
wrapper = required != null ? new PurchasableWrapperMaterials(purchasable, cost, required) : new PurchasableWrapper(purchasable, cost);
shop.addItem(wrapper);
}
@Override
public boolean canUndo() {
return wrapper != null;
}
@Override
public void undo() {
shop.removeItem(wrapper);
shop.addItem(purchasable);
}
}
@ZenMethod
@SuppressWarnings("unused")
@Deprecated //TODO: Remove in 0.7+
public static void adjustCarpenter(String input, int logs, int stone, long cost) {
String id = fixPurchasableID(input);
if (HFShops.CARPENTER.getPurchasableFromID(id) == null) CraftTweaker.logError(String.format("No purchasable with the id %s could be found in " + HFShops.CARPENTER, id));
else if (!(HFShops.CARPENTER.getPurchasableFromID(id) instanceof PurchasableMaterials)) CraftTweaker.logError(String.format("The item %s did not originally accept materials, you cannot adjust the values", id));
else MineTweakerAPI.apply(new AdjustCarpenter(HFShops.CARPENTER.getPurchasableFromID(id), cost, logs, stone));
}
private static class AdjustCarpenter extends AdjustPurchasable {
protected final int wood;
protected final int stone;
AdjustCarpenter(IPurchasable purchasable, long cost, int wood, int stone) {
super(HFShops.CARPENTER, purchasable, cost, null);
this.wood = wood;
this.stone = stone;
}
@Override
@SuppressWarnings("unchecked")
public void apply() {
shop.removeItem(purchasable); //Remove the item
wrapper = new PurchasableWrapperMaterials((PurchasableMaterials)purchasable, wood, stone, cost);
shop.addItem(wrapper);
}
}
private static String fixPurchasableID(String id) {
if (!id.startsWith("buy") || !id.startsWith("sell")) return "buy:" + id;
else return id;
}
}