package gtanks.services;

import gtanks.commands.Type;
import gtanks.lobby.LobbyManager;
import gtanks.logger.Logger;
import gtanks.main.database.DatabaseManager;
import gtanks.main.database.impl.DatabaseManagerImpl;
import gtanks.services.annotations.ServicesInject;
import gtanks.users.User;
import gtanks.users.garage.GarageItemsLoader;
import gtanks.users.garage.enums.ItemType;
import gtanks.users.garage.items.Item;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

public class GiftsServices {
    private static final GiftsServices INSTANCE = new GiftsServices();

    @ServicesInject(target = DatabaseManagerImpl.class)
    private DatabaseManager database = DatabaseManagerImpl.instance();

    private List<String> loadedGifts = new ArrayList<>(Arrays.asList("{\"item_id\":\"armor\",\"count\":30,\"rarity\":0},{\"item_id\":\"double_damage\",\"count\":30,\"rarity\":0},{\"item_id\":\"n2o\",\"count\":30,\"rarity\":0},{\"item_id\":\"mine\",\"count\":10,\"rarity\":0},{\"item_id\":\"health\",\"count\":10,\"rarity\":0},{\"item_id\":\"no_supplies\",\"count\":0,\"rarity\":0},{\"item_id\":\"lava\",\"count\":0,\"rarity\":0},{\"item_id\":\"forester\",\"count\":0,\"rarity\":0},{\"item_id\":\"armor\",\"count\":100,\"rarity\":1},{\"item_id\":\"double_damage\",\"count\":100,\"rarity\":1},{\"item_id\":\"n2o\",\"count\":100,\"rarity\":1},{\"item_id\":\"mine\",\"count\":50,\"rarity\":1},{\"item_id\":\"health\",\"count\":30,\"rarity\":1},{\"item_id\":\"surf\",\"count\":0,\"rarity\":1},{\"item_id\":\"blizzard\",\"count\":0,\"rarity\":1},{\"item_id\":\"crystalls\",\"count\":1500,\"rarity\":2},{\"item_id\":\"set_50\",\"count\":0,\"rarity\":2},{\"item_id\":\"surf\",\"count\":0,\"rarity\":2},{\"item_id\":\"mary\",\"count\":0,\"rarity\":2},{\"item_id\":\"khokhloma\",\"count\":0,\"rarity\":2},{\"item_id\":\"krio\",\"count\":0,\"rarity\":3},{\"item_id\":\"tundra\",\"count\":0,\"rarity\":3},{\"item_id\":\"crystalls\",\"count\":3000,\"rarity\":3},{\"item_id\":\"set_150\",\"count\":0,\"rarity\":3},{\"item_id\":\"frezeeny\",\"count\":0,\"rarity\":4},{\"item_id\":\"dictatorny\",\"count\":0,\"rarity\":4},{\"item_id\":\"crystalls\",\"count\":8000,\"rarity\":4}"));

    public static GiftsServices instance() {
        return INSTANCE;
    }

    public void userOnGiftsWindowOpen(LobbyManager lobby) {
        lobby.send(Type.LOBBY, "show_gifts_window", String.valueOf(this.loadedGifts), String.valueOf((lobby.getLocalUser().getGarage().getItemById("gift")).count));
    }

    public void tryRollItem(LobbyManager lobby) {
        String itemName, itemId = null;
        int countItems = 0;
        int rarity = 0;
        int offsetCrystalls = 0;
        try {
            JSONArray jsonArray = parseJsonArray(String.valueOf(this.loadedGifts));
            JSONObject randomItem = pickRandomItem(jsonArray);
            itemId = (String)randomItem.get("item_id");
            rarity = ((Long)randomItem.get("rarity")).intValue();
            countItems = ((Long)randomItem.get("count")).intValue();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (itemId.startsWith("set_")) {
            String countString = itemId.substring(4);
            int setItemCount = Integer.parseInt(countString);
            itemName = "+" + setItemCount;
            addBonusItemsToGarage(lobby.getLocalUser(), setItemCount);
        } else if (itemId.equals("crystalls")) {
            itemName = "x" + countItems;
            lobby.dummyAddCrystall(countItems);
            offsetCrystalls = countItems;
        } else {
            itemName = getItemNameWithCount(lobby, itemId, countItems);
            offsetCrystalls = getOffsetCrystalls(lobby, (Item)GarageItemsLoader.items.get(itemId));
            rewardGiftItemToUser(lobby, (Item)GarageItemsLoader.items.get(itemId));
        }
        Logger.debug("User " + lobby.getLocalUser().getNickname() + " added item " + itemName + " to garage");
        Item item = lobby.getLocalUser().getGarage().getItemById("gift");
        updateInventory(lobby, item, 1);
        lobby.send(Type.LOBBY, "item_rolled", itemId, "" + countItems + ";" + countItems, itemName + ";" + itemName);
    }

    public void rollItems(LobbyManager lobby, int rollCount) {
        JSONArray jsonArrayGift = new JSONArray();
        int offsetCrystalls = 0;
        StringBuilder resultLogs = new StringBuilder("[GIFT_SYSTEM_LOG_OUT]: Details:");
        resultLogs.append(" Nickname: ").append(lobby.getLocalUser().getNickname());
        resultLogs.append(" gifts opened count: ").append(rollCount).append("\n");
        try {
            JSONArray jsonArray = parseJsonArray(String.valueOf(this.loadedGifts));
            for (int i = 0; i < rollCount; i++) {
                String itemName;
                JSONObject randomItem = pickRandomItem(jsonArray);
                String itemId = (String)randomItem.get("item_id");
                int rarity = ((Long)randomItem.get("rarity")).intValue();
                int countItems = ((Long)randomItem.get("count")).intValue();
                JSONArray numInventoryCounts = new JSONArray();
                for (int j = 0; j < 5; j++)
                    numInventoryCounts.add(Integer.valueOf(0));
                if (itemId.startsWith("set_")) {
                    String countString = itemId.substring(4);
                    int setItemCount = Integer.parseInt(countString);
                    itemName = "+" + setItemCount;
                    addBonusItemsToGarage(lobby.getLocalUser(), setItemCount);
                } else if (itemId.equals("crystalls")) {
                    itemName = "x" + countItems;
                    lobby.dummyAddCrystall(countItems);
                } else {
                    itemName = getItemNameWithCount(lobby, itemId, countItems);
                    offsetCrystalls = getOffsetCrystalls(lobby, (Item)GarageItemsLoader.items.get(itemId));
                    rewardGiftItemToUser(lobby, (Item)GarageItemsLoader.items.get(itemId));
                }
                resultLogs.append("===================================\n");
                resultLogs.append("[GIFT_SYSTEM_LOG_OUT]: Prize: ").append(itemName).append("\n");
                JSONObject newItem = new JSONObject();
                newItem.put("itemId", itemId);
                newItem.put("visualItemName", itemName);
                newItem.put("rarity", Integer.valueOf(rarity));
                newItem.put("offsetCrystalls", Integer.valueOf(offsetCrystalls));
                newItem.put("numInventoryCounts", numInventoryCounts);
                jsonArrayGift.add(newItem);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Logger.debug(String.valueOf(resultLogs));
        Item item = lobby.getLocalUser().getGarage().getItemById("gift");
        updateInventory(lobby, item, rollCount);
        lobby.send(Type.LOBBY,"items_rolled", String.valueOf(jsonArrayGift));
    }

    private void updateInventory(LobbyManager lobby, Item item, int amountToRemove) {
        item.count -= amountToRemove;
        if (item.count <= 0)
            (lobby.getLocalUser().getGarage()).items.remove(item);
        lobby.getLocalUser().getGarage().parseJSONData();
        this.database.update(lobby.getLocalUser().getGarage());
    }

    private String getItemNameWithCount(LobbyManager lobby, String itemId, int countItems) {
        String itemName = ((Item)GarageItemsLoader.items.get(itemId)).name.localizatedString(lobby.getLocalUser().getLocalization());
        List<String> specialItemIds = Arrays.asList("mine", "n2o", "health", "armor", "double_damage");
        if (specialItemIds.contains(itemId)) {
            Item bonusItem = lobby.getLocalUser().getGarage().getItemById(itemId);
            if (bonusItem == null) {
                bonusItem = ((Item)GarageItemsLoader.items.get(itemId)).clone();
                (lobby.getLocalUser().getGarage()).items.add(bonusItem);
            }
            bonusItem.count += countItems;
            itemName = itemName + " x" + countItems;
        }
        return itemName;
    }

    private void rewardGiftItemToUser(LobbyManager lobby, Item item) {
        boolean containsItem = lobby.getLocalUser().getGarage().containsItem(item.id);
        if (containsItem) {
            if (item.itemType != ItemType.INVENTORY) {
                lobby.dummyAddCrystall(item.price / 2);
                Logger.log("User " + lobby.getLocalUser().getNickname() + " contains item in garage reward: " + item.price / 2 + " crystals.");
            }
        } else {
            (lobby.getLocalUser().getGarage()).items.add((Item)GarageItemsLoader.items.get(item.id));
        }
    }

    private int getOffsetCrystalls(LobbyManager lobby, Item item) {
        boolean containsItem = lobby.getLocalUser().getGarage().containsItem(item.id);
        int offsetCrystalls = 0;
        if (containsItem &&
                item.itemType != ItemType.INVENTORY) {
            offsetCrystalls = item.price / 2;
            Logger.log("User " + lobby.getLocalUser().getNickname() + " offsetCrystalls: " + offsetCrystalls);
        }
        return offsetCrystalls;
    }

    public static JSONArray parseJsonArray(String jsonArrayString) throws ParseException {
        JSONParser jsonParser = new JSONParser();
        return (JSONArray)jsonParser.parse(jsonArrayString);
    }

    private void addBonusItemsToGarage(User localUser, int setItemCount) {
        Logger.log("addBonusItemsToGarage()::setItemCount: " + setItemCount);
        List<String> bonusItemIds = Arrays.asList("n2o", "double_damage", "armor", "mine", "health");
        for (String bonusItemId : bonusItemIds) {
            Item bonusItem = localUser.getGarage().getItemById(bonusItemId);
            if (bonusItem == null) {
                bonusItem = ((Item)GarageItemsLoader.items.get(bonusItemId)).clone();
                (localUser.getGarage()).items.add(bonusItem);
            }
            bonusItem.count += setItemCount;
        }
    }

    public static JSONObject pickRandomItem(JSONArray jsonArray) {
        Random random = new Random();
        int[] rarityProbabilities = { 50, 34, 10, 5, 1 };
        int totalProbabilitySum = 0;
        for (int i = 0; i < rarityProbabilities.length; i++)
            totalProbabilitySum += rarityProbabilities[i];
        int randomValue = random.nextInt(totalProbabilitySum);
        int cumulativeProbability = 0;
        int rarity = 0;
        for (int j = 0; j < rarityProbabilities.length; j++) {
            cumulativeProbability += rarityProbabilities[j];
            if (randomValue < cumulativeProbability) {
                rarity = j;
                break;
            }
        }
        ArrayList<JSONObject> itemsWithRarity = new ArrayList<>();
        for (int k = 0; k < jsonArray.size(); k++) {
            JSONObject item = (JSONObject)jsonArray.get(k);
            int itemRarity = ((Long)item.get("rarity")).intValue();
            if (itemRarity == rarity)
                itemsWithRarity.add(item);
        }
        if (itemsWithRarity.size() > 0) {
            int randomIndex = random.nextInt(itemsWithRarity.size());
            return itemsWithRarity.get(randomIndex);
        }
        return (JSONObject)jsonArray.get(0);
    }
}
как loadedGifts перенести в json файл