// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!

   \page qtpurchasing-gettingstarted-qml.html
   \title Getting Started with Qt Purchasing in QML
   \brief Guide to getting started with Qt Purchasing using QML.

   This guide assumes that you have registered the in-app products for your
   application in the external store. For more information about registering
   products, see \l{Registering Products in Google Play} and
   \l{Registering Products in App Store}.

   \section1 Preparing the application

   Register and import your QML types. The QML types can be imported into your
   application for example using the following import statement:

   \qml \QtMinorVersion
   import com.mycompany.myappname
   \endqml

   And by adding following statements in the \c .pro file to link against defined QML types:

   \code
   CONFIG += qmltypes
   QML_IMPORT_NAME = com.mycompany.myappname
   QML_IMPORT_MAJOR_VERSION = 1
   \endcode

   For more information check out \l{https://doc.qt.io/qt-5/qtqml-cppintegration-definetypes.html}{Defining QML Types from C++}.

   \section1 Registering products

   Before you can operate on the products in your code, they must be
   registered in the QML graph. You start by making a Store item,
   and then create each product as a child of this.

   \qml
   Store {
      Product {
         identifier: "consumableProduct"
         type: Product.Consumable

         // ...
      }

      Product {
         identifier: "unlockableProduct"
         type: Product.Unlockable

         // ...
      }
   }
   \endqml

   As you can see, there are consumable products and unlockable products. The former
   can be purchased any number of times by the same user, while the latter can only
   be purchased once.

   \section1 The product declaration

   For each product you must fill out the \c identifier, before the product can
   be queried from the external store. You should also always add a \c{QtPurchasing::Product::onPurchaseSucceeded}
   and a \c{QtPurchasing::Product::onPurchaseFailed} handler if you intend to
   provide the option to purchase the products. If you are also using the
   restore functionality, you should add a
   \c{QtPurchasing::Product::onPurchaseRestored} handler to your unlockable
   products.

   The signal handlers should handle the incoming transaction. Once the transaction
   has been handled appropriately, it should be finalized. For instance, when a purchase
   has succeeded, it's appropriate to save information about the purchased product in
   persistent storage, so that this product can still be available the next time the
   application launches.

   The following example calls custom methods to save data about a succeeded purchase so that
   it survives across application runs. After verifying that the data has been stored, it finalizes
   the transaction. When the transaction has failed, it displays information about the failure
   to the user and finalizes the transaction.

   \qml
   Store {
      id: store
      Product {
         id: healthPotionProduct
         identifier: "healthPotion"
         type: Product.Consumable

         property bool purchasing: false

         onPurchaseSucceeded: {
            if (!hasAlreadyStoredTransaction(transaction.orderId)) {
               ++healthPotions
               if (!addHealthPotionToPersistentStorage(transaction.orderId)) {
                  popupErrorDialog(qsTr("Unable to write to persistent storage. Please make sure there is sufficient space and restart."))
               } else {
                  transaction.finalize()
               }
            }

            // Reset purchasing flag
            purchasing = false
         }

         onPurchaseFailed: {
            popupErrorDialog(qsTr("Purchase not completed."))
            transaction.finalize()

            // Reset purchasing flag
            purchasing = false
         }
      }
   }
   \endqml

   If a transaction is not finalized, it will be called again for the same transaction the next time the application
   starts up, providing another chance to store the data. The transaction for a consumable product has
   to be finalized before the product can be purchased again.

   \section1 Purchasing a product

   In order to purchase a product, call the object's purchase() method. This launches a platform-specific, asynchronous
   process to purchase the product, for example by requesting the user's password and confirmation of the purchase.
   In most cases, you should make sure that the application UI is not accepting input while the purchasing request
   is being processed, as this is not handled automatically on all platforms.

   The following example adds a button to be used with the example product in the previous section:
   \qml
   Rectangle {
      id: button
      width: 100
      height: 50

      Text {
         anchors.centerIn: parent
         text: qsTr("Buy health potion for only " + healthPotionProduct.price + "!")
      }

      MouseArea {
         enabled: !healthPotionProduct.purchasing && healthPotionProduct.status === Product.Registered
         anchors.fill: parent
         onClicked: {
            healthPotionProduct.purchasing = true
            healthPotionProduct.purchase()
         }
      }
   }
   \endqml

   When the button is clicked, the purchase process is started. At some point in the future, either the
   \c{QtPurchasing::Product::onPurchaseFailed} handler will be called (for example if the user cancels the transaction), or the
   \c{QtPurchasing::Product::onPurchaseSucceeded} handler will be called.

   \note The button is only enabled if the product's status is set to Registered. The registration process
   for a product is asynchronous, so purchases attempted on a product before it has been successfully registered
   will always fail.

   \section1 Restoring previously purchased products

   If the application is uninstalled and subsequently reinstalled (or installed by the same user on
   a different device) you should provide a way to restore the previously purchased unlockable products
   in the external market place.

   To start the process of restoring purchases, you should call the restorePurchases() method in the
   \c Store object. This will cause the onPurchaseRestored handler to be called in each of the application's
   unlockable products that has previously been purchased by the current user.

   Continuing on the example from before, which could be some sort of role-playing computer game, lets imagine
   that the game has downloadable content that you can buy to expand the game further. This should be an unlockable product,
   because the user should not have to purchase it more than once.

   \qml
   Store {
      id: store

      // ... other products

      Product {
         id: dlcForestOfFooBarProduct
         identifier: "dlcForestOfFooBar"
         type: Product.Unlockable

         property bool purchasing: false

         onPurchaseSucceeded: {
            if (!hasMap("forestOfFooBar.map")) {
               if (!downloadExtraMap("forestOfFooBar.map")) {
                  popupErrorDialog(qsTr("Unable to download The Forest of FooBar map. Please make sure there is sufficient space and restart."))
               } else {
                  transaction.finalize()
               }
            }

            // Reset purchasing flag
            purchasing = false
         }

         onPurchaseFailed: {
            popupErrorDialog(qsTr("Purchase not completed."))
            transaction.finalize()

            // Reset purchasing flag
            purchasing = false
         }

         onPurchaseRestored: {
            if (!hasMap("forestOfFooBar.map")) {
               if (!downloadExtraMap("forestOfFooBar.map")) {
                  popupErrorDialog(qsTr("Unable to download The Forest of FooBar map. Please make sure there is sufficient space and restart."))
               } else {
                  transaction.finalize()
               }
            }
         }
      }
   }
   \endqml

   If a user buys the downloadable content and later either installs the game on another device or uninstalls and reinstalls the game,
   you can provide a way to restore the purchase, such as the following button:

   \qml
   Rectangle {
      id: restoreButton
      width: 100
      height: 50

      Text {
         anchors.centerIn: parent
         text: "Restore previously purchased content"
      }

      MouseArea {
         anchors.fill: parent
         onClicked: {
            store.restorePurchases()
         }
      }
   }
   \endqml

   Restoring purchases should always be done as a reaction to user input, as it may present a password dialog on some platforms.
   Calling the restorePurchases() method launches the restore process asynchronously. At some point in the future the onPurchaseRestored
   handler will be called if the product has previously been purchased.

   \note While the function behaves as documented on Android, this functionality is technically not needed there. The reason for this
   is that the Android device manages all unlockable purchases with no intervention from the application. If an application is
   uninstalled and reinstalled (or installed on a different device) on Android, then onPurchaseSucceeded will be called for each previously
   purchased, unlockable product when the application starts up.
*/

