// -----------------------------------------------------------------------------------
 // Show
 // -----------------------------------------------------------------------------------
 public void Show(string message, int minAmount, int maxAmount, UCE_UI_InputCallback callbackObject)
 {
     instance              = callbackObject;
     messageText.text      = message;
     amountSlider.value    = 0;
     amountSlider.minValue = minAmount;
     amountSlider.maxValue = maxAmount;
     amountText.text       = amountSlider.value.ToString() + "/" + maxAmount.ToString();
     panel.SetActive(true);
 }
    // -----------------------------------------------------------------------------------
    // Update
    // -----------------------------------------------------------------------------------
    private void Update()
    {
        Player player = Player.localPlayer;

        if (!player)
        {
            return;
        }

        if (instance == null)
        {
            instance = this.GetComponent <UCE_UI_InputCallback>();
        }

        if (player.target != null && player.target is Npc &&
            Utils.ClosestDistance(player.collider, player.target.collider) <= player.interactionRange)
        {
            Npc npc = (Npc)player.target;

            // --------------------------------------------------------------------------- Check Confirmation

            if (instance != null && instance.confirmed && instance.chosenAmount > 0 && instance.selectedID > -1)
            {
                if (sellMode)
                {
                    ConfirmSell(instance.chosenAmount, instance.selectedID);
                }
                else
                {
                    ConfirmBuy(instance.chosenAmount, instance.selectedID);
                }

                instance.Reset();
            }

            // --------------------------------------------------------------------------- Refresh Sale Items

            List <ScriptableItem> saleItems = new List <ScriptableItem>();
            saleItems.AddRange(npc.saleItems);

            if (npc.shopContent.scaleContentWithPlayer)
            {
                saleItems.Clear();

                int idx = Mathf.Max((Mathf.RoundToInt(player.level / (player.maxLevel / npc.shopContent.levelSaleItems.Length)) - 1), 0);

                if (npc.shopContent.showAllValidContent)
                {
                    for (int i = 0; i <= idx; ++i)
                    {
                        saleItems.AddRange(npc.shopContent.levelSaleItems[i].saleItems);
                    }
                }
                else
                {
                    if (npc.shopContent.levelSaleItems.Length > 0)
                    {
                        saleItems.AddRange(npc.shopContent.levelSaleItems[idx].saleItems);
                    }
                }
            }
            else
            {
                if (npc.shopContent.levelSaleItems.Length > 0 && npc.shopContent.levelSaleItems.Length >= npc.level)
                {
                    saleItems.Clear();
                    saleItems.AddRange(npc.shopContent.levelSaleItems[npc.level - 1].saleItems);
                }
            }

            // instantiate/destroy enough category slots
            UIUtils.BalancePrefabs(categorySlotPrefab.gameObject, npc.shopContent.shopCategories.Length, categoryContent);

            // --------------------------------------------------------------------------- Refresh Mode Button
            if (sellMode)
            {
                buttonSwitchMode.GetComponentInChildren <Text>().text = buyText;
                buttonSwitchMode.onClick.SetListener(() =>
                {
                    ClearContent();
                    sellMode = false;
                });
            }
            else
            {
                buttonSwitchMode.GetComponentInChildren <Text>().text = sellText;
                buttonSwitchMode.onClick.SetListener(() =>
                {
                    ClearContent();
                    sellMode = true;
                });
            }

            // --------------------------------------------------------------------------- Refresh Category Buttons
            for (int i = 0; i < npc.shopContent.shopCategories.Length; ++i)
            {
                Button button = categoryContent.GetChild(i).GetComponent <Button>();
                button.interactable = npc.shopContent.shopCategories[i] != currentCategory;

                if (npc.shopContent.shopCategories[i] == "")
                {
                    button.GetComponentInChildren <Text>().text = emptyCategoryLabel;
                }
                else
                {
                    button.GetComponentInChildren <Text>().text = npc.shopContent.shopCategories[i];
                }

                int icopy = i; // needed for lambdas, otherwise i is Count
                button.onClick.SetListener(() =>
                {
                    currentCategory = npc.shopContent.shopCategories[icopy];
                    ScrollToBeginning();
                });
            }

            // --------------------------------------------------------------------------- Update Content (Buy Mode)
            if (!sellMode && npc.shopContent.shopCategories.Length > 0)
            {
                // instantiate/destroy enough item slots for that category
                ScriptableItem[] items = saleItems.Where(x => x.itemCategory == currentCategory || currentCategory == "").ToArray();
                UIUtils.BalancePrefabs(itemSlotPrefab.gameObject, items.Length, itemContent);

                // refresh all items in that category
                for (int i = 0; i < items.Length; ++i)
                {
                    UCE_UI_NpcShopSlot slot     = itemContent.GetChild(i).GetComponent <UCE_UI_NpcShopSlot>();
                    ScriptableItem     itemData = items[i];

                    slot.tooltip.text           = new Item(itemData).ToolTip();
                    slot.image.color            = Color.white;
                    slot.image.sprite           = itemData.image;
                    slot.nameText.text          = itemData.name;
                    slot.priceText.text         = itemData.buyPrice.ToString();
                    slot.buyText.text           = buyText;
                    slot.buyButton.interactable = player.isAlive && player.gold >= itemData.buyPrice;
                    int icopy  = i; // needed for lambdas, otherwise i is Count
                    int maxBuy = MaxBuyAmount(player, itemData);
                    slot.buyButton.onClick.SetListener(() =>
                    {
                        if (maxBuy == 1)
                        {
                            ConfirmBuy(1, icopy);
                        }
                        else
                        {
                            instance.Show(buyAmountText, 1, maxBuy, icopy);
                        }
                    });
                }
            }

            // --------------------------------------------------------------------------- Update Content (Sell Mode)
            if (sellMode && npc.shopContent.shopCategories.Length > 0)
            {
                int j         = 0;
                int itemCount = player.inventory.Count(x => x.amount > 0 && x.item.data.sellable && (x.item.data.itemCategory == currentCategory || currentCategory == ""));
                UIUtils.BalancePrefabs(itemSlotPrefab.gameObject, itemCount, itemContent);

                // refresh all items in that category
                for (int i = 0; i < player.inventory.Count; ++i)
                {
                    if (player.inventory[i].amount > 0 && (player.inventory[i].item.data.sellable && (player.inventory[i].item.data.itemCategory == currentCategory || currentCategory == "")))
                    {
                        UCE_UI_NpcShopSlot slot     = itemContent.GetChild(j).GetComponent <UCE_UI_NpcShopSlot>();
                        ScriptableItem     itemData = player.inventory[i].item.data;

                        slot.tooltip.text           = new Item(itemData).ToolTip();
                        slot.image.color            = Color.white;
                        slot.image.sprite           = itemData.image;
                        slot.nameText.text          = itemData.name + " x" + player.inventory[i].amount;
                        slot.priceText.text         = itemData.sellPrice.ToString();
                        slot.buyText.text           = sellText;
                        slot.buyButton.interactable = player.isAlive && player.inventory[i].amount > 0;
                        int icopy = i; // needed for lambdas, otherwise i is Count
                        slot.buyButton.onClick.SetListener(() =>
                        {
                            if (player.inventory[icopy].amount == 1)
                            {
                                ConfirmSell(1, icopy);
                            }
                            else
                            {
                                instance.Show(sellAmountText, 1, player.inventory[icopy].amount, icopy);
                            }
                            ClearContent();
                            inventoryPanel.SetActive(true); // better feedback
                        });
                        j++;
                    }
                }
            }

            // --------------------------------------------------------------------------- Update Overview
            currencyAmountText.text = player.gold.ToString();
        }
        else
        {
            if (instance != null)
            {
                instance.Reset();
            }
            panel.SetActive(false);
        }
    }