content: module Reddit.Types.Listing where
  
  import Reddit.Parser
  
  import Control.Applicative
  import Data.Aeson
  import Data.Traversable
  import Data.Semigroup
  import Network.API.Builder.Query
  import Prelude
  
  data ListingType = Hot
                   | New
                   | Rising
                   | Controversial
                   | Top
    deriving (Show, Read, Eq)
  
  instance ToQuery ListingType where
    toQuery k t = return $ (,) k $ case t of
      Hot -> "hot"
      New -> "new"
      Rising -> "rising"
      Controversial -> "controversial"
      Top -> "top"
  
  data Listing t a = Listing { before :: Maybe t
                             , after :: Maybe t
                             , contents :: [a] }
    deriving (Show, Read, Eq)
  
  instance Functor (Listing t) where
    fmap f (Listing b a x) = Listing b a (fmap f x)
  
  instance Ord t => Semigroup (Listing t a) where
    Listing a b cs <> Listing d e fs =
      Listing (max a d) (min b e) (cs <> fs)
  
  instance Ord t => Monoid (Listing t a) where
    mappend = (<>)
    mempty = Listing Nothing Nothing []
  
  instance (FromJSON t, FromJSON a) => FromJSON (Listing t a) where
    parseJSON (Object o) = do
      o `ensureKind` "Listing"
      d <- o .: "data"
      Listing <$> (d .:? "before" >>= traverse parseJSON)
              <*> (d .:? "after" >>= traverse parseJSON)
              <*> (o .: "data" >>= (.: "children"))
    parseJSON (String "") = return $ Listing Nothing Nothing []
    parseJSON Null = return $ Listing Nothing Nothing []
    parseJSON _ = mempty
  