content: {-# LANGUAGE FlexibleInstances     #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE OverloadedStrings     #-}
  {-# LANGUAGE TypeFamilies          #-}
  -------------------------------------------
  -- |
  -- Module      : Web.Stripe.Subscription
  -- Copyright   : (c) David Johnson, 2014
  -- Maintainer  : code@dmj.io
  -- Stability   : experimental
  -- Portability : POSIX
  --
  -- < https:/\/\stripe.com/docs/api#subscriptions >
  --
  -- @
  -- {-\# LANGUAGE OverloadedStrings \#-}
  -- import Web.Stripe
  -- import Web.Stripe.Subscription
  -- import Web.Stripe.Customer
  -- import Web.Stripe.Plan
  --
  -- main :: IO ()
  -- main = do
  --   let config = StripeConfig (StripeKey "secret_key")
  --   result <- stripe config $ createCustomer
  --   case result of
  --     (Left stripeError) -> print stripeError
  --     (Right (Customer { customerId = cid })) -> do
  --       result <- stripe config $ createPlan (PlanId "free plan")
  --                                            (Amount 0)
  --                                            USD
  --                                            Month
  --                                            (PlanName "sample plan")
  --       case result of
  --         (Left stripeError) -> print stripeError
  --         (Right (Plan { planId = pid })) -> do
  --            result <- stripe config $ createSubscription cid pid
  --            case result of
  --              (Left stripeError)   -> print stripeError
  --              (Right subscription) -> print subscription
  -- @
  module Web.Stripe.Subscription
      ( -- * API
        CreateSubscription
      , createSubscription
      , GetSubscription
      , getSubscription
      , UpdateSubscription
      , updateSubscription
      , CancelSubscription
      , cancelSubscription
      , GetSubscriptions
      , getSubscriptions
      , GetSubscriptionsByCustomerId
      , getSubscriptionsByCustomerId
        -- * Types
      , ApplicationFeePercent (..)
      , AtPeriodEnd        (..)
      , CustomerId         (..)
      , CouponId           (..)
      , Coupon             (..)
      , EndingBefore       (..)
      , ExpandParams       (..)
      , Limit              (..)
      , MetaData           (..)
      , PlanId             (..)
      , Prorate            (..)
      , Quantity           (..)
      , StartingAfter      (..)
      , StripeList         (..)
      , Subscription       (..)
      , SubscriptionId     (..)
      , SubscriptionStatus (..)
      , TaxPercent         (..)
      , TrialEnd           (..)
      ) where
  
  import           Web.Stripe.StripeRequest   (Method (GET, POST, DELETE),
                                               StripeHasParam, StripeReturn,
                                               StripeRequest (..),
                                               ToStripeParam(..), mkStripeRequest)
  import           Web.Stripe.Util            ((</>))
  import           Web.Stripe.Types           (ApplicationFeePercent(..),
                                               AtPeriodEnd(..), CardId(..),
                                               CustomerId (..), Coupon(..),
                                               CouponId(..), EndingBefore(..),
                                               ExpandParams(..), Limit(..), MetaData(..),
                                               PlanId (..), Prorate(..), Quantity(..),
                                               StartingAfter(..),
                                               Subscription (..), StripeList(..),
                                               SubscriptionId (..),
                                               SubscriptionStatus (..), TaxPercent(..), 
                                               TrialEnd(..))
  import           Web.Stripe.Types.Util      (getCustomerId)
  
  ------------------------------------------------------------------------------
  -- | Create a `Subscription` by `CustomerId` and `PlanId`
  createSubscription
      :: CustomerId -- ^ The `CustomerId` upon which to create the `Subscription`
      -> PlanId     -- ^ The `PlanId` to associate the `Subscription` with
      -> StripeRequest CreateSubscription
  createSubscription
      customerid
      planId = request
    where request = mkStripeRequest POST url params
          url     = "customers" </> getCustomerId customerid </> "subscriptions"
          params  = toStripeParam planId []
  
  data CreateSubscription
  type instance StripeReturn CreateSubscription = Subscription
  instance StripeHasParam CreateSubscription CouponId
  instance StripeHasParam CreateSubscription Prorate
  instance StripeHasParam CreateSubscription TrialEnd
  instance StripeHasParam CreateSubscription CardId
  instance StripeHasParam CreateSubscription Quantity
  instance StripeHasParam CreateSubscription ApplicationFeePercent
  instance StripeHasParam CreateSubscription MetaData
  instance StripeHasParam CreateSubscription TaxPercent
  
  ------------------------------------------------------------------------------
  -- | Retrieve a `Subscription` by `CustomerId` and `SubscriptionId`
  getSubscription
      :: CustomerId       -- ^ The `CustomerId` of the `Subscription`
      -> SubscriptionId   -- ^ The `SubscriptionId` of the `Subscription` to retrieve
      -> StripeRequest GetSubscription
  getSubscription
      customerid
      (SubscriptionId subscriptionid)
                  = request
    where request = mkStripeRequest GET url params
          url     = "customers" </> getCustomerId customerid </>
                    "subscriptions" </> subscriptionid
          params  = []
  
  data GetSubscription
  type instance StripeReturn GetSubscription = Subscription
  instance StripeHasParam GetSubscription ExpandParams
  
  ------------------------------------------------------------------------------
  -- | Update a `Subscription` by `CustomerId` and `SubscriptionId`
  updateSubscription
      :: CustomerId      -- ^ The `CustomerId` of the `Subscription` to update
      -> SubscriptionId  -- ^ The `SubscriptionId` of the `Subscription` to update
      -> StripeRequest UpdateSubscription
  updateSubscription
     customerid
      (SubscriptionId subscriptionid)
    = request
    where request = mkStripeRequest POST url params
          url     = "customers" </> getCustomerId customerid </> "subscriptions" </> subscriptionid
          params  = []
  
  data UpdateSubscription
  type instance StripeReturn UpdateSubscription = Subscription
  instance StripeHasParam UpdateSubscription PlanId
  instance StripeHasParam UpdateSubscription CouponId
  instance StripeHasParam UpdateSubscription Prorate
  instance StripeHasParam UpdateSubscription TrialEnd
  instance StripeHasParam UpdateSubscription CardId
  instance StripeHasParam UpdateSubscription Quantity
  instance StripeHasParam UpdateSubscription ApplicationFeePercent
  instance StripeHasParam UpdateSubscription MetaData
  instance StripeHasParam UpdateSubscription TaxPercent
  
  ------------------------------------------------------------------------------
  -- | Delete a `Subscription` by `CustomerId` and `SubscriptionId`
  cancelSubscription
      :: CustomerId     -- ^ The `CustomerId` of the `Subscription` to cancel
      -> SubscriptionId -- ^ The `SubscriptionId` of the `Subscription` to cancel
      -> StripeRequest CancelSubscription
  cancelSubscription
      customerid
      (SubscriptionId subscriptionid)
       = request
    where request = mkStripeRequest DELETE url params
          url     = "customers" </> getCustomerId customerid </> "subscriptions" </> subscriptionid
          params  = []
  
  data CancelSubscription
  instance StripeHasParam CancelSubscription AtPeriodEnd
  type instance StripeReturn CancelSubscription = Subscription
  
  ------------------------------------------------------------------------------
  -- | Retrieve all active `Subscription`s
  getSubscriptions
      :: StripeRequest GetSubscriptions
  getSubscriptions
      = request
    where request = mkStripeRequest GET url params
          url     = "subscriptions"
          params  = []
  
  data GetSubscriptions
  type instance StripeReturn GetSubscriptions = StripeList Subscription
  instance StripeHasParam GetSubscriptions ExpandParams
  instance StripeHasParam GetSubscriptions (EndingBefore SubscriptionId)
  instance StripeHasParam GetSubscriptions Limit
  instance StripeHasParam GetSubscriptions (StartingAfter SubscriptionId)
  
  ------------------------------------------------------------------------------
  -- | Retrieve a customer's `Subscription`s
  getSubscriptionsByCustomerId
      :: CustomerId
      -> StripeRequest GetSubscriptionsByCustomerId
  getSubscriptionsByCustomerId
      customerid = request
    where request = mkStripeRequest GET url params
          url     = "customers" </> getCustomerId customerid </> "subscriptions"
          params  = []
  
  data GetSubscriptionsByCustomerId
  type instance StripeReturn GetSubscriptionsByCustomerId = StripeList Subscription
  instance StripeHasParam GetSubscriptionsByCustomerId ExpandParams
  instance StripeHasParam GetSubscriptionsByCustomerId (EndingBefore SubscriptionId)
  instance StripeHasParam GetSubscriptionsByCustomerId Limit
  instance StripeHasParam GetSubscriptionsByCustomerId (StartingAfter SubscriptionId)
  