{-|
Module      : SimFin.Types.PricesQuery
Description : Types to represent SimFin price queries.
Copyright   : (c) Owen Shepherd, 2022
License     : MIT
Maintainer  : owen@owen.cafe
-}

{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module SimFin.Types.PricesQuery
  ( PricesQuery(..)
  , PricesQueryFree
  , pricesQueryToQueryParams
  , pricesQueryFreeToQueryParams
  ) where

import Data.List.NonEmpty (NonEmpty)
import Data.Maybe (maybeToList)
import Data.Time.Calendar (Day)

import SimFin.Types.StockRef
import SimFin.Internal

-- | This represents all options the prices endpoint supports.
-- Some of these parameters are only available to SimFin+ users.
-- For free users, please use 'PricesQueryFree'.

data PricesQuery
  = PricesQuery
  { PricesQuery -> NonEmpty StockRef
stockRefs :: NonEmpty StockRef
  , PricesQuery -> Maybe Day
start :: Maybe Day
  , PricesQuery -> Maybe Day
end :: Maybe Day
  , PricesQuery -> Bool
asReported :: Bool
  } deriving Int -> PricesQuery -> ShowS
[PricesQuery] -> ShowS
PricesQuery -> String
(Int -> PricesQuery -> ShowS)
-> (PricesQuery -> String)
-> ([PricesQuery] -> ShowS)
-> Show PricesQuery
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PricesQuery] -> ShowS
$cshowList :: [PricesQuery] -> ShowS
show :: PricesQuery -> String
$cshow :: PricesQuery -> String
showsPrec :: Int -> PricesQuery -> ShowS
$cshowsPrec :: Int -> PricesQuery -> ShowS
Show

-- | Represents all the parameters available to free users.

type PricesQueryFree = StockRef

-- | Turn a 'PricesQuery' into query parameters for the SimFin "prices" endpoint.

pricesQueryToQueryParams :: PricesQuery -> [QueryParam]
pricesQueryToQueryParams :: PricesQuery -> [QueryParam]
pricesQueryToQueryParams PricesQuery{Bool
Maybe Day
NonEmpty StockRef
asReported :: Bool
end :: Maybe Day
start :: Maybe Day
stockRefs :: NonEmpty StockRef
$sel:asReported:PricesQuery :: PricesQuery -> Bool
$sel:end:PricesQuery :: PricesQuery -> Maybe Day
$sel:start:PricesQuery :: PricesQuery -> Maybe Day
$sel:stockRefs:PricesQuery :: PricesQuery -> NonEmpty StockRef
..} = 
  let
    refParams :: [QueryParam]
refParams = NonEmpty StockRef -> [QueryParam]
stockRefsToQueryParams NonEmpty StockRef
stockRefs
    startParam :: [QueryParam]
startParam = ByteString -> [Day] -> [QueryParam]
forall a. Show a => ByteString -> [a] -> [QueryParam]
toShownCommaQueryParam ByteString
"start "([Day] -> [QueryParam]) -> [Day] -> [QueryParam]
forall a b. (a -> b) -> a -> b
$ Maybe Day -> [Day]
forall a. Maybe a -> [a]
maybeToList Maybe Day
start
    endParam :: [QueryParam]
endParam = ByteString -> [Day] -> [QueryParam]
forall a. Show a => ByteString -> [a] -> [QueryParam]
toShownCommaQueryParam ByteString
"end" ([Day] -> [QueryParam]) -> [Day] -> [QueryParam]
forall a b. (a -> b) -> a -> b
$ Maybe Day -> [Day]
forall a. Maybe a -> [a]
maybeToList Maybe Day
end
    asReportedParam :: [QueryParam]
asReportedParam = ByteString -> Bool -> [QueryParam]
toBoolQueryParam ByteString
"asreported" Bool
asReported
  in
  [[QueryParam]] -> [QueryParam]
forall a. Monoid a => [a] -> a
mconcat
    [ [QueryParam]
refParams
    , [QueryParam]
startParam
    , [QueryParam]
endParam
    , [QueryParam]
asReportedParam
    ]

freeToPlus :: PricesQueryFree -> PricesQuery
freeToPlus :: StockRef -> PricesQuery
freeToPlus StockRef
stockRef
  = PricesQuery :: NonEmpty StockRef -> Maybe Day -> Maybe Day -> Bool -> PricesQuery
PricesQuery
  { $sel:stockRefs:PricesQuery :: NonEmpty StockRef
stockRefs = StockRef -> NonEmpty StockRef
forall (f :: * -> *) a. Applicative f => a -> f a
pure StockRef
stockRef
  , $sel:start:PricesQuery :: Maybe Day
start = Maybe Day
forall a. Maybe a
Nothing
  , $sel:end:PricesQuery :: Maybe Day
end = Maybe Day
forall a. Maybe a
Nothing
  , $sel:asReported:PricesQuery :: Bool
asReported = Bool
False
  }

-- | Turn a 'PricesQueryFree' into query parameters for the SimFin "prices" endpoint.

pricesQueryFreeToQueryParams :: PricesQueryFree -> [QueryParam]
pricesQueryFreeToQueryParams :: StockRef -> [QueryParam]
pricesQueryFreeToQueryParams = PricesQuery -> [QueryParam]
pricesQueryToQueryParams (PricesQuery -> [QueryParam])
-> (StockRef -> PricesQuery) -> StockRef -> [QueryParam]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StockRef -> PricesQuery
freeToPlus