/// <summary>
        /// Buys the purchasable virtual item.
        /// Implementation in subclasses will be according to specific type of purchase.
        /// </summary>
        /// <param name="payload">a string you want to be assigned to the purchase. This string
        /// is saved in a static variable and will be given bacl to you when the
        ///  purchase is completed.</param>
        /// <exception cref="Soomla.Store.InsufficientFundsException">throws InsufficientFundsException</exception>
        public override void Buy(string payload)
        {
            SoomlaUtils.LogDebug("SOOMLA PurchaseWithVirtualItem", "Trying to buy a " + AssociatedItem.Name + " with "
                                 + Amount + " pieces of " + TargetItemId);

            VirtualItem item = getTargetVirtualItem();

            if (item == null)
            {
                return;
            }


            JSONObject eventJSON = new JSONObject();

            eventJSON.AddField("itemId", AssociatedItem.ItemId);
            StoreEvents.Instance.onItemPurchaseStarted(eventJSON.print(), true);

            if (!checkTargetBalance(item))
            {
                throw new InsufficientFundsException(TargetItemId);
            }

            item.Take(Amount);

            AssociatedItem.Give(1);

            // We have to make sure the ItemPurchased event will be fired AFTER the balance/currency-changed events.
            StoreEvents.Instance.RunLater(() => {
                eventJSON = new JSONObject();
                eventJSON.AddField("itemId", AssociatedItem.ItemId);
                eventJSON.AddField("payload", payload);
                StoreEvents.Instance.onItemPurchased(eventJSON.print(), true);
            });
        }
        /// <summary>
        /// Buys the purchasable virtual item.
        /// Implementation in subclasses will be according to specific type of purchase.
        /// </summary>
        /// <param name="payload">a string you want to be assigned to the purchase. This string
        /// is saved in a static variable and will be given bacl to you when the
        ///  purchase is completed.</param>
        /// <exception cref="Soomla.Store.InsufficientFundsException">throws InsufficientFundsException</exception>
        public override void Buy(string payload)
        {
            SoomlaUtils.LogDebug("SOOMLA PurchaseWithVirtualItem", "Trying to buy a " + AssociatedItem.Name + " with "
                                 + Amount + " pieces of " + TargetItemId);

            VirtualItem item = null;

            try {
                item = StoreInfo.GetItemByItemId(TargetItemId);
            } catch (VirtualItemNotFoundException) {
                SoomlaUtils.LogError(TAG, "Target virtual item doesn't exist !");
                return;
            }

            JSONObject eventJSON = new JSONObject();

            eventJSON.AddField("itemId", AssociatedItem.ItemId);
            StoreEvents.Instance.onItemPurchaseStarted(eventJSON.print());

            int balance = item.GetBalance();

            if (item is VirtualCurrency)
            {
                balance = VirtualCurrencyStorage.GetBalance(item);
            }
            else
            {
                balance = VirtualGoodsStorage.GetBalance(item);
            }

            if (balance < Amount)
            {
                throw new InsufficientFundsException(TargetItemId);
            }

            item.Take(Amount);

            AssociatedItem.Give(1);

            eventJSON = new JSONObject();
            eventJSON.AddField("itemId", AssociatedItem.ItemId);
            eventJSON.AddField("payload", payload);
            StoreEvents.Instance.onItemPurchased(eventJSON.print());
        }
        /// <summary>
        /// Buys the purchasable virtual item.
        /// Implementation in subclasses will be according to specific type of purchase.
        /// </summary>
        /// <param name="payload">a string you want to be assigned to the purchase. This string
        /// is saved in a static variable and will be given bacl to you when the
        ///  purchase is completed.</param>
        /// <exception cref="Soomla.Store.InsufficientFundsException">throws InsufficientFundsException</exception>
        public override void Buy(string payload)
        {
            SoomlaUtils.LogDebug("SOOMLA PurchaseWithVirtualItem", "Trying to buy a " + AssociatedItem.Name + " with "
                                 + Amount + " pieces of " + TargetItemId);

            VirtualItem item = null;

            try {
                item = StoreInfo.GetItemByItemId(TargetItemId);
            } catch (VirtualItemNotFoundException) {
                SoomlaUtils.LogError(TAG, "Target virtual item doesn't exist !");
                return;
            }

            JSONObject eventJSON = new JSONObject();

            eventJSON.AddField("itemId", AssociatedItem.ItemId);
            StoreEvents.Instance.onItemPurchaseStarted(eventJSON.print(), true);

            int balance = item.GetBalance();

            if (balance < Amount)
            {
                throw new InsufficientFundsException(TargetItemId);
            }

            item.Take(Amount);

            AssociatedItem.Give(1);

            // We have to make sure the ItemPurchased event will be fired AFTER the balance/currency-changed events.
            StoreEvents.Instance.RunLater(() => {
                eventJSON = new JSONObject();
                eventJSON.AddField("itemId", AssociatedItem.ItemId);
                eventJSON.AddField("payload", payload);
                StoreEvents.Instance.onItemPurchased(eventJSON.print(), true);
            });
        }