{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE NamedFieldPuns #-}
module JSON (
    exportBlog
  ) where

import Blog (Blog, Path, Skin, URL, Wording)
import qualified Blog (Blog(..))
import Data.Aeson (Options(..), ToJSON(..), genericToEncoding, defaultOptions)
import Data.Map (Map, mapWithKey)
import qualified Data.Map as Map (filter, keys)
import qualified Data.Set as Set (elems, member)
import GHC.Generics
import Markdown (Markdown, MarkdownContent(..))
import qualified Markdown (Markdown(..))

data MarkdownExport = MarkdownExport {
      MarkdownExport -> String
title :: String
    , MarkdownExport -> Map String String
metadata :: Map String String
    , MarkdownExport -> Int
bodyOffset :: Int
    , MarkdownExport -> Maybe [String]
tagged :: Maybe [String]
  } deriving ((forall x. MarkdownExport -> Rep MarkdownExport x)
-> (forall x. Rep MarkdownExport x -> MarkdownExport)
-> Generic MarkdownExport
forall x. Rep MarkdownExport x -> MarkdownExport
forall x. MarkdownExport -> Rep MarkdownExport x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MarkdownExport x -> MarkdownExport
$cfrom :: forall x. MarkdownExport -> Rep MarkdownExport x
Generic)

instance ToJSON MarkdownExport where
  toEncoding :: MarkdownExport -> Encoding
toEncoding = Options -> MarkdownExport -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (Options
defaultOptions {omitNothingFields :: Bool
omitNothingFields = Bool
True})

exportMarkdown :: Maybe [String] -> Markdown -> MarkdownExport
exportMarkdown :: Maybe [String] -> Markdown -> MarkdownExport
exportMarkdown Maybe [String]
tagged Markdown
markdown = MarkdownExport :: String
-> Map String String -> Int -> Maybe [String] -> MarkdownExport
MarkdownExport {
      title :: String
title = Markdown -> String
Markdown.title Markdown
markdown
    , metadata :: Map String String
metadata = Markdown -> Map String String
Markdown.metadata Markdown
markdown
    , bodyOffset :: Int
bodyOffset = Markdown -> Int
Markdown.bodyOffset Markdown
markdown
    , Maybe [String]
tagged :: Maybe [String]
tagged :: Maybe [String]
tagged
  }

data BlogExport = BlogExport {
      BlogExport -> Map String MarkdownExport
articles :: Map String MarkdownExport
    , BlogExport -> Bool
hasRSS :: Bool
    , BlogExport -> Path
path :: Path
    , BlogExport -> Map String MarkdownExport
pages :: Map String MarkdownExport
    , BlogExport -> Skin
skin :: Skin
    , BlogExport -> Map String [String]
tags :: Map String [String]
    , BlogExport -> URL
urls :: URL
    , BlogExport -> Wording
wording :: Wording
  } deriving ((forall x. BlogExport -> Rep BlogExport x)
-> (forall x. Rep BlogExport x -> BlogExport) -> Generic BlogExport
forall x. Rep BlogExport x -> BlogExport
forall x. BlogExport -> Rep BlogExport x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep BlogExport x -> BlogExport
$cfrom :: forall x. BlogExport -> Rep BlogExport x
Generic)

instance ToJSON BlogExport where
  toEncoding :: BlogExport -> Encoding
toEncoding = Options -> BlogExport -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding Options
defaultOptions

exportBlog :: Blog -> BlogExport
exportBlog :: Blog -> BlogExport
exportBlog Blog
blog = BlogExport :: Map String MarkdownExport
-> Bool
-> Path
-> Map String MarkdownExport
-> Skin
-> Map String [String]
-> URL
-> Wording
-> BlogExport
BlogExport {
      articles :: Map String MarkdownExport
articles = Map String Markdown -> Map String MarkdownExport
getArticles (Map String Markdown -> Map String MarkdownExport)
-> Map String Markdown -> Map String MarkdownExport
forall a b. (a -> b) -> a -> b
$ Article -> Markdown
forall a. MarkdownContent a => a -> Markdown
getMarkdown (Article -> Markdown) -> Map String Article -> Map String Markdown
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Blog -> Map String Article
Blog.articles Blog
blog
    , hasRSS :: Bool
hasRSS = Blog -> Bool
Blog.hasRSS Blog
blog
    , pages :: Map String MarkdownExport
pages = Map String Markdown -> Map String MarkdownExport
forall k. Map k Markdown -> Map k MarkdownExport
getPages (Map String Markdown -> Map String MarkdownExport)
-> Map String Markdown -> Map String MarkdownExport
forall a b. (a -> b) -> a -> b
$ Page -> Markdown
forall a. MarkdownContent a => a -> Markdown
getMarkdown (Page -> Markdown) -> Map String Page -> Map String Markdown
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Blog -> Map String Page
Blog.pages Blog
blog
    , path :: Path
path = Blog -> Path
Blog.path Blog
blog
    , skin :: Skin
skin = Blog -> Skin
Blog.skin Blog
blog
    , tags :: Map String [String]
tags = Set String -> [String]
forall a. Set a -> [a]
Set.elems (Set String -> [String])
-> Map String (Set String) -> Map String [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Blog -> Map String (Set String)
Blog.tags Blog
blog
    , urls :: URL
urls = Blog -> URL
Blog.urls Blog
blog
    , wording :: Wording
wording = Blog -> Wording
Blog.wording Blog
blog
  }
  where
    tag :: String -> Maybe [String]
tag String
key = [String] -> Maybe [String]
forall a. a -> Maybe a
Just ([String] -> Maybe [String])
-> (Map String (Set String) -> [String])
-> Map String (Set String)
-> Maybe [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map String (Set String) -> [String]
forall k a. Map k a -> [k]
Map.keys (Map String (Set String) -> [String])
-> (Map String (Set String) -> Map String (Set String))
-> Map String (Set String)
-> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Set String -> Bool)
-> Map String (Set String) -> Map String (Set String)
forall a k. (a -> Bool) -> Map k a -> Map k a
Map.filter (String -> Set String -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member String
key) (Map String (Set String) -> Maybe [String])
-> Map String (Set String) -> Maybe [String]
forall a b. (a -> b) -> a -> b
$ Blog -> Map String (Set String)
Blog.tags Blog
blog
    getArticles :: Map String Markdown -> Map String MarkdownExport
getArticles = (String -> Markdown -> MarkdownExport)
-> Map String Markdown -> Map String MarkdownExport
forall k a b. (k -> a -> b) -> Map k a -> Map k b
mapWithKey (Maybe [String] -> Markdown -> MarkdownExport
exportMarkdown (Maybe [String] -> Markdown -> MarkdownExport)
-> (String -> Maybe [String])
-> String
-> Markdown
-> MarkdownExport
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe [String]
tag)
    getPages :: Map k Markdown -> Map k MarkdownExport
getPages = (k -> Markdown -> MarkdownExport)
-> Map k Markdown -> Map k MarkdownExport
forall k a b. (k -> a -> b) -> Map k a -> Map k b
mapWithKey (\k
_-> Maybe [String] -> Markdown -> MarkdownExport
exportMarkdown Maybe [String]
forall a. Maybe a
Nothing)