content: {-# LANGUAGE FlexibleInstances     #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE OverloadedStrings     #-}
  {-# LANGUAGE TypeFamilies          #-}
  -------------------------------------------
  -- |
  -- Module      : Web.Stripe.Charge
  -- Copyright   : (c) David Johnson, 2014
  -- Maintainer  : code@dmj.io
  -- Stability   : experimental
  -- Portability : POSIX
  --
  -- < https:/\/\stripe.com/docs/api#charges >
  --
  -- @
  -- {-\# LANGUAGE OverloadedStrings \#-}
  -- import Web.Stripe
  -- import Web.Stripe.Customer
  -- import Web.Stripe.Charge
  --
  -- main :: IO ()
  -- main = do
  --   let config = StripeConfig (StripeKey "secret_key")
  --       credit = CardNumber "4242424242424242"
  --       em  = ExpMonth 12
  --       ey  = ExpYear 2015
  --       cvc = CVC "123"
  --       cardinfo = (newCard credit em ey) { newCardCVC = Just cvc }
  --   result <- stripe config createCustomer
  --                              -&- cardinfo
  --   case result of
  --     (Left stripeError) -> print stripeError
  --     (Customer { customerId = cid }) ->
  --       do result <- stripe config $ createCharge (Amount 100) USD
  --                                      -&- cid
  --          case result of
  --            Left  stripeError -> print stripeError
  --            Right charge      -> print charge
  -- @
  module Web.Stripe.Charge
      ( -- * API
        ---- * Create Charges
        CreateCharge
      , createCharge
        ---- * Get Charge(s)
      , GetCharge
      , getCharge
      , GetCharges
      , getCharges
        ---- * Update Charge
      , UpdateCharge
      , updateCharge
        ---- * Capture Charge
      , CaptureCharge
      , captureCharge
        -- * Types
      , Amount        (..)
      , ApplicationFeeAmount(..)
      , CardNumber    (..)
      , Capture       (..)
      , Charge        (..)
      , ChargeId      (..)
      , Created       (..)
      , Currency      (..)
      , CustomerId    (..)
      , Customer      (..)
      , CVC           (..)
      , Description   (..)
      , Email         (..)
      , EndingBefore  (..)
      , ExpandParams  (..)
      , ExpMonth      (..)
      , ExpYear       (..)
      , Limit         (..)
      , MetaData      (..)
      , NewCard       (..)
      , ReceiptEmail  (..)
      , StartingAfter (..)
      , StatementDescription (..)
      , StripeList    (..)
      , TokenId       (..)
      ) where
  
  import           Web.Stripe.StripeRequest   (Method (GET, POST),
                                               StripeHasParam, ToStripeParam(..),
                                               StripeRequest (..), StripeReturn,
                                               mkStripeRequest)
  import           Web.Stripe.Util            ((</>))
  import           Web.Stripe.Types           (Amount(..), ApplicationFeeAmount(..),
                                               CVC (..),
                                               Capture(..),
                                               CardNumber (..), Charge (..),
                                               ChargeId (..), Created(..),
                                               Currency (..), Customer(..),
                                               CustomerId (..), Description(..),
                                               EndingBefore(..), ExpMonth (..),
                                               ExpYear (..), Limit(..), MetaData(..),
                                               NewCard(..), Email (..),
                                               StartingAfter(..),
                                               ReceiptEmail(..),
                                               StatementDescription(..),
                                               ExpandParams(..),
                                               StripeList (..), TokenId (..))
  import           Web.Stripe.Types.Util      (getChargeId)
  
  ------------------------------------------------------------------------------
  -- | Create a `Charge`
  createCharge
      :: Amount   -- ^ `Amount` to charge
      -> Currency -- ^ `Currency` for charge
      -> StripeRequest CreateCharge
  createCharge
      amount
      currency = request
    where request = mkStripeRequest POST url params
          url     = "charges"
          params  = toStripeParam amount   $
                    toStripeParam currency $
                    []
  
  data CreateCharge
  type instance StripeReturn CreateCharge = Charge
  instance StripeHasParam CreateCharge ExpandParams
  instance StripeHasParam CreateCharge CustomerId
  instance StripeHasParam CreateCharge NewCard
  instance StripeHasParam CreateCharge TokenId
  instance StripeHasParam CreateCharge Description
  instance StripeHasParam CreateCharge MetaData
  instance StripeHasParam CreateCharge Capture
  instance StripeHasParam CreateCharge StatementDescription
  instance StripeHasParam CreateCharge ReceiptEmail
  instance StripeHasParam CreateCharge ApplicationFeeAmount
  
  ------------------------------------------------------------------------------
  -- | Retrieve a `Charge` by `ChargeId`
  getCharge
      :: ChargeId -- ^ The `Charge` to retrive
      -> StripeRequest GetCharge
  getCharge
      chargeid    = request
    where request = mkStripeRequest GET url params
          url     = "charges" </> getChargeId chargeid
          params  = []
  
  data GetCharge
  type instance StripeReturn GetCharge = Charge
  instance StripeHasParam GetCharge ExpandParams
  
  ------------------------------------------------------------------------------
  -- | A `Charge` to be updated
  updateCharge
      :: ChargeId    -- ^ The `Charge` to update
      -> StripeRequest UpdateCharge
  updateCharge
      chargeid    = request
    where request = mkStripeRequest POST url params
          url     = "charges" </> getChargeId chargeid
          params  = []
  
  data UpdateCharge
  type instance StripeReturn UpdateCharge = Charge
  instance StripeHasParam UpdateCharge Description
  instance StripeHasParam UpdateCharge MetaData
  
  ------------------------------------------------------------------------------
  -- | a `Charge` to be captured
  captureCharge
      :: ChargeId     -- ^ The `ChargeId` of the `Charge` to capture
      -> StripeRequest CaptureCharge
  captureCharge
      chargeid     = request
    where request  = mkStripeRequest POST url params
          url      = "charges" </> getChargeId chargeid </> "capture"
          params   = []
  
  data CaptureCharge
  type instance StripeReturn CaptureCharge = Charge
  instance StripeHasParam CaptureCharge Amount
  instance StripeHasParam CaptureCharge ReceiptEmail
  
  ------------------------------------------------------------------------------
  -- | Retrieve all `Charge`s
  getCharges
      :: StripeRequest GetCharges
  getCharges = request
    where request = mkStripeRequest GET url params
          url     = "charges"
          params  = []
  
  data GetCharges
  type instance StripeReturn GetCharges = StripeList Charge
  instance StripeHasParam GetCharges ExpandParams
  instance StripeHasParam GetCharges Created
  instance StripeHasParam GetCharges CustomerId
  instance StripeHasParam GetCharges (EndingBefore ChargeId)
  instance StripeHasParam GetCharges Limit
  instance StripeHasParam GetCharges (StartingAfter ChargeId)
  