package de.iani.treasurechest;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;

import org.bukkit.scheduler.BukkitRunnable;

import de.iani.treasurechest.database.DatabaseTreasureChestItem;
import de.iani.treasurechest.database.TreasureChestDatabase;
import de.iani.treasurechest.worker.WorkEntry;

public class PlayerTreasureChestContent {
    private final TreasureChest plugin;
    private final UUID owner;

    private LoadState loadState = LoadState.NOT_LOADED;

    private ArrayList<DatabaseTreasureChestItem> items;
    private HashMap<Integer, DatabaseTreasureChestItem> itemsById;
    private ArrayList<Runnable> loadCallbacks;

    public PlayerTreasureChestContent(UUID owner, TreasureChest plugin) {
        this.plugin = plugin;
        this.owner = owner;
    }

    public void loadAsync(Runnable loadCallback) {
        if (loadCallback != null) {
            if (loadState == LoadState.LOADED) {
                loadCallback.run();
                return;
            }
            if (loadCallbacks == null) {
                loadCallbacks = new ArrayList<>();
            }
            loadCallbacks.add(loadCallback);
        }
        loadAsync();
    }

    public void loadAsync() {
        if (loadState != LoadState.NOT_LOADED) {
            return;
        }
        loadState = LoadState.LOADING;
        plugin.getWorkerThread().addWork(new WorkEntry() {
            @Override
            public void process(TreasureChestDatabase database) {
                try {
                    ArrayList<DatabaseTreasureChestItem> loadedItems = plugin.getDatabase().getPlayerItems(owner);
                    new BukkitRunnable() {
                        @Override
                        public void run() {
                            items = loadedItems;
                            itemsById = new HashMap<>();
                            for (DatabaseTreasureChestItem i : items) {
                                itemsById.put(i.getId(), i);
                            }
                            loadState = LoadState.LOADED;

                            if (loadCallbacks != null) {
                                for (Runnable r : loadCallbacks) {
                                    r.run();
                                }
                                loadCallbacks = null;
                            }
                        }
                    }.runTask(plugin);
                } catch (SQLException e) {
                    plugin.getLogger().log(Level.SEVERE, "Could not load treasure chest data for " + owner + ": " + e, e);
                }
            }
        });
    }

    // public PlayerTreasureChestContent(UUID owner, TreasureChest plugin, File file) {
    // this.plugin = plugin;
    // this.file = file;
    // try {
    // if (file.exists()) {
    // YamlConfiguration conf = YamlConfiguration.loadConfiguration(file);
    //
    // ConfigurationSection prices = conf.getConfigurationSection("prices");
    // if (prices != null) {
    // for (String e : prices.getKeys(false)) {
    // ConfigurationSection price = prices.getConfigurationSection(e);
    // if (price != null) {
    // ItemStack display = price.getItemStack("displayItem");
    // if (display == null) {
    // display = new ItemStack(Material.BEDROCK);
    // ItemMeta meta = display.getItemMeta();
    // meta.setDisplayName("Unset displayitem");
    // display.setItemMeta(meta);
    // }
    // int priceMoney = price.getInt("priceMoney");
    // ArrayList<ItemStack> priceItems = new ArrayList<>();
    // ConfigurationSection itemPricesSection = price.getConfigurationSection("itemPrices");
    // if (itemPricesSection != null) {
    // for (String pricee : itemPricesSection.getKeys(false)) {
    // ItemStack priceItem = itemPricesSection.getItemStack(pricee);
    // if (priceItem != null) {
    // priceItems.add(priceItem);
    // }
    // }
    // }
    // if (items == null) {
    // items = new ArrayList<>();
    // }
    // items.add(new TreasureChestItem(display, priceItems.toArray(new ItemStack[priceItems.size()]), priceMoney));
    // }
    // }
    // }
    // }
    // } catch (Exception e) {
    // plugin.getLogger().log(Level.SEVERE, "Could not load user chest file: " + file.getName(), e);
    // }
    // }

    // private void save() {
    // file.getParentFile().mkdirs();
    // YamlConfiguration conf = new YamlConfiguration();
    // ConfigurationSection prices = conf.createSection("prices");
    // if (items != null) {
    // int nr = 0;
    // for (TreasureChestItem i : items) {
    // ConfigurationSection price = prices.createSection(Integer.toString(nr++));
    // price.set("displayItem", i.getDisplayItem().clone());
    // price.set("priceMoney", i.getPriceMoney());
    // ConfigurationSection itemsSec = price.createSection("itemPrices");
    // if (i.getPriceItems() != null) {
    // int nr2 = 0;
    // for (ItemStack st : i.getPriceItems()) {
    // itemsSec.set(Integer.toString(nr2++), st.clone());
    // }
    // }
    // }
    // }
    // try {
    // conf.save(file);
    // } catch (IOException e) {
    // plugin.getLogger().log(Level.SEVERE, "Could not save user chest file: " + file.getName(), e);
    // }
    // }

    void addItem(DatabaseTreasureChestItem item) {
        item = item.clone();
        if (items == null) {
            items = new ArrayList<>();
            itemsById = new HashMap<>();
        }
        items.add(0, item);
        itemsById.put(item.getId(), item);
    }

    public boolean removeItem(int id) {
        if (itemsById == null) {
            return false;
        }
        DatabaseTreasureChestItem removed = itemsById.remove(id);
        if (removed != null) {
            items.remove(removed);
        }
        return true;
    }

    public boolean isEmpty() {
        return items == null || items.isEmpty();
    }

    public List<DatabaseTreasureChestItem> getItems() {
        return items == null ? Collections.emptyList() : Collections.unmodifiableList(items);
    }

    public DatabaseTreasureChestItem getItem(int id) {
        return itemsById.get(id);
    }

    public LoadState getLoadState() {
        return loadState;
    }

    public UUID getOwner() {
        return owner;
    }

    public enum LoadState {
        NOT_LOADED, LOADING, LOADED
    }
}
