{-# LANGUAGE OverloadedStrings #-}
module Network.Shopify.Types (
    ShopifyID
  , JsonExtending(..), ShopifyMeta(..), ShopifyDate(..), dateToQuery
  , ProductID, LineItemID, CollectionID, OrderID
  , Sku
  ) where

import Data.Int
import Control.Applicative
import qualified Data.Text as T
import Data.Aeson ((.:), (.=))
import qualified Data.Aeson as JS
import qualified Data.Aeson.Types as JS
import qualified Data.ByteString as BS
import Data.Time
import Network.HTTP.Types.QueryLike (toQueryValue)


type ShopifyID = Int64
type ProductID = ShopifyID
type LineItemID = ShopifyID
type CollectionID = ShopifyID
type OrderID = ShopifyID

type Sku = T.Text

class JsonExtending a where
  jsonExtender :: a -> [JS.Pair]

dateToQuery :: UTCTime -> Maybe BS.ByteString
dateToQuery = toQueryValue . formatTime defaultTimeLocale (iso8601DateFormat $ Just "")

data ShopifyDate = ShopifyDate {actualTime::UTCTime}

instance JS.FromJSON ShopifyDate where
  parseJSON (JS.String t) =
    case parseTimeM True defaultTimeLocale "%FT%T%Z" (T.unpack t) of
      Just d  -> pure $ ShopifyDate d
      Nothing -> fail "could not parse ISO-8601 date"
  parseJSON v            = fail ("ShopifyDate not a string: "++show v)

instance JS.ToJSON ShopifyDate where
  toJSON (ShopifyDate t) = JS.String (T.pack $ formatTime defaultTimeLocale "%FT%T%z" t)

data ShopifyMeta =
  ShopifyMeta {
      metaId :: ShopifyID
    , metaCreated :: UTCTime
    , metaUpdated :: UTCTime
    }
  deriving (Show)

instance JsonExtending ShopifyMeta where
  jsonExtender m =
    ["id" .= metaId m
    ,"created_at" .= (ShopifyDate $ metaCreated m)
    ,"updated_at" .= (ShopifyDate $ metaUpdated m)
    ]

instance JS.FromJSON ShopifyMeta where
  parseJSON (JS.Object v) = ShopifyMeta <$>
                            v .: "id" <*>
                            (v .: "created_at" >>= return . actualTime) <*>
                            (v .: "updated_at" >>= return . actualTime)
  parseJSON _          = fail "ShopifyMeta not an object"