//
//  MTX.h
//
//  Created by Machine Union (dev361) on 2013-04-12.
//  Copyright (c) 2013 Electronic Arts. All rights reserved.
//

#ifndef MTX_h
#define MTX_h

#pragma once

#include "NimbleBase/NimbleCppTypes.h"
#include "NimbleBridge/FastDelegate.h"
#include "NimbleBase/Error.h"
#include "NimbleMTX/MTXTransaction.h"
#include "NimbleMTX/MTXCatalogItem.h"
#include "MTXError.h"

/*!
 * NIMBLE_NOTIFICATION_MTX_REFRESH_CATALOG_FINISHED
 *
 * Sent in response to refreshAvailableCatalogItems()
 *
 * UserInfo keys:
 *  NIMBLE_ERROR - Error object, if query error'd.
 */
#define NIMBLE_NOTIFICATION_MTX_REFRESH_CATALOG_FINISHED "nimble.notification.mtx.refreshcatalogfinished"

/*!
 * NIMBLE_NOTIFICATION_MTX_RESTORE_PURCHASED_TRANSACTIONS_FINISHED
 *
 * Sent in response to refreshPurchasedItems
 *
 * UserInfo keys:
 *  NIMBLE_ERROR - Error object, if refresh error'd.
 */
#define NIMBLE_NOTIFICATION_MTX_RESTORE_PURCHASED_TRANSACTIONS_FINISHED "nimble.notification.mtx.restorepurchasedtransactionsfinished"

/*!
 * NIMBLE_NOTIFICATION_MTX_TRANSACTIONS_RECOVERED
 *
 * Sent on startup if there are pending transactions without callbacks.
 *
 * UserInfo keys:
 *
 */
#define NIMBLE_NOTIFICATION_MTX_TRANSACTIONS_RECOVERED "nimble.notification.mtx.transactionsrecovered"

namespace EA
{

namespace Nimble
{

namespace MTX
{

enum PromotedPaymentAction
    {
        PROMOTED_PAYMENT_DELAY,
        PROMOTED_PAYMENT_ACKNOWLEDGED
    };

enum StorePromotionVisibility
{
	DEFAULT,
	HIDE,
	SHOW
};
    
typedef fastdelegate::FastDelegate1<const MTXTransaction&> TransactionCallback;
typedef fastdelegate::FastDelegate<void (const Base::Error&)> RefreshReceiptCallback;
typedef nimstl::function<PromotedPaymentAction (const nimstl::string&)> PromotedPaymentCallback;
typedef nimstl::function<void (const nimstl::vector<nimstl::string>& skus, const Base::Error&)> PromotedItemsCallback;
typedef nimstl::function<void (const Base::Error&)> CompletionCallback;
typedef nimstl::function<void (StorePromotionVisibility visibility, const Base::Error& error)> StorePromotionVisibilityCallback;
    
class MTX
{
public:
	
	/*!
     * Purchase an item given an item identifier. Optional: Include metadata (e.g. offer code) that will be added to the transaction.
     * Returns Error object on error. Null if no immediate error.
     */
    Base::Error purchaseItem(const nimstl::string& sku, TransactionCallback unverifiedReceiptCallback, TransactionCallback purchaseCompleteCallback, const nimstl::string& metadata = "");

	/*!
     * Consume the given item/transaction. Where necessary, this makes the notification to the billing platform
     * that the item has been granted. Indicate if this was a consumable or non-consumable item.
     *
     * Note: Game should call itemGranted() immediately after granting the item to the player to avoid exploit 
     *       where user interrupts the app between item grant and GooglePlay consumption, then restores purchases
     *       and gets the same item again through the restore.
     *
     * @param transactionId
     * @param itemType
     * @param callback
     * @return Error object on error. Null if no immediate error.
     */
	Base::Error itemGranted(const nimstl::string& transactionId, MTXCatalogItem::Type itemType, TransactionCallback callback);

	/*!
     * Game calls this to acknowledge the purchase notification, for both successes and errors.
     *
     * @param transactionId
     * @param callback
     */
	Base::Error finalizeTransaction(const nimstl::string& transactionId, TransactionCallback callback);

	/*!
     * Get list of already purchased items, as list of SKU strings.
     * This list does not include history of consumable items.
     * This list does not included subscription items (not supported).
     * Game notified of completion via notification, NIMBLE_NOTIFICATION_MTX_RESTORE_PURCHASED_TRANSACTIONS_FINISHED.
     */
	void restorePurchasedTransactions();

	/*!
     * Get already purchased items as a list of NimbleMTXTransactions. The transaction object includes receipts
     * and additional info.
     *
     * @return
     */
	nimstl::vector<MTXTransaction> getPurchasedTransactions();

	/*!
     * Get list of in-progress transactions that have not been finalized.
     */
	nimstl::vector<MTXTransaction> getPendingTransactions();

	/*!
     * Get list of purchase transactions recovered from a previous session. Call resumeTransaction to continue the process.
     *
     * @return
     */
	nimstl::vector<MTXTransaction> getRecoveredTransactions();

	/*!
     * Resume a recovered transaction.
     *
     * @param transactionId
     * @param callback
     *
     */
	Base::Error resumeTransaction(const nimstl::string& transactionId, TransactionCallback unverifiedReceiptCallback, TransactionCallback purchaseCompleteCallback, TransactionCallback itemGrantedCallback, TransactionCallback finalizeCallback);

	/*!
     *  Initiate a refresh of the entire catalog. No filter.
     */
	void refreshAvailableCatalogItems();

	/*!
     * Get the list of available items.
     */
	nimstl::vector<MTXCatalogItem> getAvailableCatalogItems();

	/*!
     * Set MTX platform specific parameters in a key-value map.  It is up to the MTX component implementation to understand the key-value passed in.
     */
	void setPlatformParameters(nimstl::map<nimstl::string, nimstl::string> parameters);

	/*!
     * Force to refresh application receipt. Callback returns with error in case of any failures.
     */
	void refreshReceiptForAllTransactions(RefreshReceiptCallback callback);
    
#ifdef NIMBLE_PLATFORM_IOS
    /*!
     * Registers promoted payment handler which returns a NimbleMTXPromotedPaymentAction depending on if the promoted payment should be continued, delayed, or canceled.
     * This callback is used to determine the action to take when a user initiates a promoted payment through the Apple store. iOS only.
     */
    void registerPromotedPaymentHandler(PromotedPaymentCallback callback);
    
    void fetchStorePromotionOrder(PromotedItemsCallback callback);

    void updateStorePromotionOrder(const nimstl::vector<nimstl::string>& skuOrder, CompletionCallback callback);

	void fetchStorePromotionVisibility(const nimstl::string& sku, StorePromotionVisibilityCallback callback);

	void updateStorePromotionVisibility(const nimstl::string& sku, StorePromotionVisibility visibility, CompletionCallback callback);
#endif
    
	static MTX getComponent();

private:

	MTX();
	MTX(const MTX&) { }
	MTX& operator=(const MTX&);
};

}

}

}

#endif
