// • ▌ ▄ ·.  ▄▄▄·  ▄▄ • ▪   ▄▄· ▄▄▄▄·  ▄▄▄·  ▐▄▄▄  ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀  █▪▀▀▀ ▀  ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀  ▀  ▀ ▀▀  █▪ ▀▀▀
//      Magicbane Emulator Project © 2013 - 2022
//                www.magicbane.com

package engine.loot;

import engine.mbEnums;
import engine.objects.Item;
import engine.objects.NPC;
import org.json.JSONObject;

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class WorkOrder implements Delayed {

    public int workOrderID;
    public NPC vendor;
    public int slots_used;
    public int total_to_produce;
    public int total_produced;
    public boolean multiple_slot_request;
    public HashMap<mbEnums.ResourceType, Integer> production_cost = new HashMap<>();
    public HashMap<mbEnums.ResourceType, Integer> production_cost_total = new HashMap<>();
    public int templateID;
    public String item_name_override;
    public int prefixToken;
    public int suffixToken;
    public long rollingDuration;
    public long completionTime;
    public boolean runCompleted = false;
    public boolean runCanceled = false;
    public ConcurrentHashMap.KeySetView<Item, Boolean> cooking = ConcurrentHashMap.newKeySet();

    public WorkOrder() {

    }

    public WorkOrder(JSONObject jsonWorkOrder) {

        this.vendor = NPC.getNPC(jsonWorkOrder.getInt("vendor"));
        this.slots_used = jsonWorkOrder.getInt("slots_used");
        this.total_to_produce = jsonWorkOrder.getInt("total_to_produce");
        this.total_produced = jsonWorkOrder.getInt("total_produced");
        this.multiple_slot_request = jsonWorkOrder.getBoolean("multiple_slot_request");
        this.templateID = jsonWorkOrder.getInt("templateID");
        this.item_name_override = jsonWorkOrder.getString("item_name_override");
        this.prefixToken = jsonWorkOrder.getInt("prefixToken");
        this.suffixToken = jsonWorkOrder.getInt("suffixToken");
        this.slots_used = jsonWorkOrder.getInt("slots_used");
        this.rollingDuration = jsonWorkOrder.getLong("rollingDuration");
        this.completionTime = jsonWorkOrder.getLong("completionTime");
        this.runCompleted = jsonWorkOrder.getBoolean("runCompleted");

        JSONObject productionCostMap = jsonWorkOrder.getJSONObject("production_cost");

        for (String key : productionCostMap.keySet()) {
            mbEnums.ResourceType resourceType = mbEnums.ResourceType.valueOf(key);
            int value = productionCostMap.getInt(key);
            this.production_cost.put(resourceType, value);
        }

        JSONObject productionTotalCostMap = jsonWorkOrder.getJSONObject("production_cost");

        for (String key : productionTotalCostMap.keySet()) {
            mbEnums.ResourceType resourceType = mbEnums.ResourceType.valueOf(key);
            int value = productionTotalCostMap.getInt(key);
            this.production_cost_total.put(resourceType, value);
        }
    }

    public static JSONObject toJson(WorkOrder workOrder) {

        JSONObject jsonWorkOrder = new JSONObject();

        jsonWorkOrder.put("vendor", workOrder.vendor.getObjectUUID());
        jsonWorkOrder.put("slots_used", workOrder.slots_used);
        jsonWorkOrder.put("total_to_produce", workOrder.total_to_produce);
        jsonWorkOrder.put("total_produced", workOrder.total_produced);
        jsonWorkOrder.put("multiple_slot_request", workOrder.multiple_slot_request);
        jsonWorkOrder.put("production_cost", workOrder.production_cost);
        jsonWorkOrder.put("production_cost_total", workOrder.production_cost_total);
        jsonWorkOrder.put("templateID", workOrder.templateID);
        jsonWorkOrder.put("item_name_override", workOrder.item_name_override);
        jsonWorkOrder.put("prefixToken", workOrder.prefixToken);
        jsonWorkOrder.put("suffixToken", workOrder.suffixToken);
        jsonWorkOrder.put("rollingDuration", workOrder.rollingDuration);
        jsonWorkOrder.put("completionTime", workOrder.completionTime);
        jsonWorkOrder.put("runCompleted", workOrder.runCompleted);

        ArrayList<Integer[]> cookingTokens = new ArrayList<>();

        for (Item item : workOrder.cooking)
            cookingTokens.add(new Integer[]{item.prefixToken, item.suffixToken});

        jsonWorkOrder.put("cookingTokens", cookingTokens);


        return jsonWorkOrder;
    }

    @Override
    public long getDelay(TimeUnit unit) {

        long timeRemaining = completionTime - System.currentTimeMillis();
        return unit.convert(timeRemaining, TimeUnit.MILLISECONDS);

    }

    @Override
    public int compareTo(Delayed o) {
        return Long.compare(this.completionTime, ((WorkOrder) o).completionTime);
    }

    public String toString() {

        LocalDateTime localDateTime = Instant.ofEpochMilli(this.completionTime)
                .atZone(ZoneId.systemDefault()).toLocalDateTime();
        Duration duration = Duration.ofMillis(this.rollingDuration);

        String outSTring = "\r\nwordOrderID: " + this.workOrderID + "\r\n" +
                "vendor: " + this.vendor.getObjectUUID() + "\r\n" +
                "slots_used: " + this.slots_used + "\r\n" +
                "total_to_produce: " + this.total_to_produce + "\r\n" +
                "total_produced: " + this.total_produced + "\r\n" +
                "templateID: " + this.templateID + "\r\n" +
                "item_name_override: " + this.item_name_override + "\r\n" +
                "prefixToken: " + this.prefixToken + "\r\n" +
                "suffixToken: " + this.suffixToken + "\r\n" +
                "rollingDuration: " + duration + "\r\n" +
                "completionTime: " + localDateTime + "\r\n" +
                "runCompleted: " + this.runCompleted + "\r\n" +
                "runCanceled: " + this.runCanceled + "\r\n";

        return outSTring;
    }

}