-- | Defines helper functions for creating jupyter notebooks.
module Language.Drasil.JSON.Helpers where

import Prelude hiding ((<>))
import Text.PrettyPrint (Doc, text, empty, (<>), vcat, hcat)
import Data.List (intersperse)
import Data.List.Split (splitOn)
import qualified Text.JSON as J (encode)

import Language.Drasil (MaxWidthPercent)
import qualified Language.Drasil.Printing.Helpers as H
import Language.Drasil.HTML.Helpers (img)

data Variation = Class | Id

tr, td, figure, li, pa, ba :: Doc -> Doc
-- | Table row tag wrapper
tr :: Doc -> Doc
tr         = String -> [String] -> Doc -> Doc
wrap "tr" []
-- | Table cell tag wrapper
td :: Doc -> Doc
td         = String -> [String] -> Doc -> Doc
wrap "td" []
-- | Figure tag wrapper
figure :: Doc -> Doc
figure     = String -> [String] -> Doc -> Doc
wrap "figure" []
-- | List tag wrapper
li :: Doc -> Doc
li         = String -> [String] -> Doc -> Doc
wrap' "li" []
-- | Paragraph in list tag wrapper
pa :: Doc -> Doc
pa         = String -> [String] -> Doc -> Doc
wrap "p" []

ba :: Doc -> Doc
ba         = String -> [String] -> Doc -> Doc
wrap "b" []

ol, ul, table :: [String] -> Doc -> Doc
-- | Ordered list tag wrapper
ol :: [String] -> Doc -> Doc
ol       = String -> [String] -> Doc -> Doc
wrap "ol"
-- | Unordered list tag wrapper
ul :: [String] -> Doc -> Doc
ul       = String -> [String] -> Doc -> Doc
wrap "ul"
-- | Table tag wrapper
table :: [String] -> Doc -> Doc
table    = String -> [String] -> Doc -> Doc
wrap "table"

nbformat :: Doc -> Doc
nbformat :: Doc -> Doc
nbformat s :: Doc
s = String -> Doc
text ("    " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
forall a. JSON a => a -> String
J.encode (Doc -> String
forall a. Show a => a -> String
show Doc
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ "\n") String -> String -> String
forall a. [a] -> [a] -> [a]
++ ",")

wrap :: String -> [String] -> Doc -> Doc
wrap :: String -> [String] -> Doc -> Doc
wrap a :: String
a = ([Doc] -> Doc)
-> Variation -> String -> Doc -> [String] -> Doc -> Doc
wrapGen' [Doc] -> Doc
vcat Variation
Class String
a Doc
empty

wrap' :: String -> [String] -> Doc -> Doc
wrap' :: String -> [String] -> Doc -> Doc
wrap' a :: String
a = ([Doc] -> Doc)
-> Variation -> String -> Doc -> [String] -> Doc -> Doc
wrapGen' [Doc] -> Doc
hcat Variation
Class String
a Doc
empty

wrapGen' :: ([Doc] -> Doc) -> Variation -> String -> Doc -> [String] -> Doc -> Doc
wrapGen' :: ([Doc] -> Doc)
-> Variation -> String -> Doc -> [String] -> Doc -> Doc
wrapGen' sepf :: [Doc] -> Doc
sepf _ s :: String
s _ [] = \x :: Doc
x -> 
  let tb :: String -> Doc
tb c :: String
c = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ "<" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ ">"
  --in sepf [quote(tb s), x, quote(tb $ '/':s)]
  in if String
s String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== "li" then [Doc] -> Doc
sepf [String -> Doc
tb String
s, Doc
x, String -> Doc
tb (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ '/'Char -> String -> String
forall a. a -> [a] -> [a]
:String
s] else [Doc] -> Doc
sepf [Doc -> Doc
nbformat(String -> Doc
tb String
s), Doc
x, Doc -> Doc
nbformat(String -> Doc
tb (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ '/'Char -> String -> String
forall a. a -> [a] -> [a]
:String
s)]
wrapGen' sepf :: [Doc] -> Doc
sepf Class s :: String
s _ ts :: [String]
ts = \x :: Doc
x ->
  let tb :: String -> Doc
tb c :: String
c = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ "<" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ " class=\\\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (String -> String -> String) -> [String] -> String
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 String -> String -> String
forall a. [a] -> [a] -> [a]
(++) (String -> [String] -> [String]
forall a. a -> [a] -> [a]
intersperse " " [String]
ts) String -> String -> String
forall a. [a] -> [a] -> [a]
++ "\\\">"
  in let te :: String -> Doc
te c :: String
c = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ "</" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ ">"
  in [Doc] -> Doc
sepf [Doc -> Doc
nbformat(String -> Doc
tb String
s), Doc
x, Doc -> Doc
nbformat(String -> Doc
te String
s)]
wrapGen' sepf :: [Doc] -> Doc
sepf Id s :: String
s ti :: Doc
ti _ = \x :: Doc
x ->
  let tb :: String -> Doc
tb c :: String
c = String -> Doc
text ("<" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ " id=\\\"") Doc -> Doc -> Doc
<> Doc
ti Doc -> Doc -> Doc
<> String -> Doc
text "\\\">"
      te :: String -> Doc
te c :: String
c = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ "</" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ ">"
  in  [Doc] -> Doc
sepf [Doc -> Doc
nbformat(String -> Doc
tb String
s), Doc
x, Doc -> Doc
nbformat(String -> Doc
te String
s)] 

refwrap :: Doc -> Doc -> Doc
refwrap :: Doc -> Doc -> Doc
refwrap = (Doc -> [String] -> Doc -> Doc) -> [String] -> Doc -> Doc -> Doc
forall a b c. (a -> b -> c) -> b -> a -> c
flip (([Doc] -> Doc)
-> Variation -> String -> Doc -> [String] -> Doc -> Doc
wrapGen' [Doc] -> Doc
vcat Variation
Id "div") [""]

refID :: Doc -> Doc 
refID :: Doc -> Doc
refID i :: Doc
i = Doc -> Doc
nbformat (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Doc
text "<a id=\"" Doc -> Doc -> Doc
<> Doc
i Doc -> Doc -> Doc
<> String -> Doc
text "\"></a>"

-- | Helper for setting up links to references
reflink :: String -> Doc -> Doc
reflink :: String -> Doc -> Doc
reflink ref :: String
ref txt :: Doc
txt = String -> Doc
text "[" Doc -> Doc -> Doc
<> Doc
txt Doc -> Doc -> Doc
<> String -> Doc
text ("](#" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ref String -> String -> String
forall a. [a] -> [a] -> [a]
++ ")")
--reflink ref txt = text ("<a href=#" ++ ref ++ ">") <> txt <> text "</a>"

-- | Helper for setting up links to external URIs
reflinkURI :: String -> Doc -> Doc
reflinkURI :: String -> Doc -> Doc
reflinkURI ref :: String
ref txt :: Doc
txt = String -> Doc
text ("<a href=\\\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ref String -> String -> String
forall a. [a] -> [a] -> [a]
++ "\\\">") Doc -> Doc -> Doc
<> Doc
txt Doc -> Doc -> Doc
<> String -> Doc
text "</a>"

-- | Helper for setting up figures
image :: Doc -> Doc -> MaxWidthPercent -> Doc
image :: Doc -> Doc -> MaxWidthPercent -> Doc
image f :: Doc
f c :: Doc
c 100 = 
  Doc -> Doc
figure (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat [
  Doc -> Doc
nbformat (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [(String, Doc)] -> Doc
img [("src", Doc
f), ("alt", Doc
c)]]
image f :: Doc
f c :: Doc
c wp :: MaxWidthPercent
wp =
  Doc -> Doc
figure (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat [
  Doc -> Doc
nbformat (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [(String, Doc)] -> Doc
img [("src", Doc
f), ("alt", Doc
c), ("width", String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ MaxWidthPercent -> String
forall a. Show a => a -> String
show MaxWidthPercent
wp String -> String -> String
forall a. [a] -> [a] -> [a]
++ "%")]]

h :: Int -> Doc
h :: Int -> Doc
h n :: Int
n       | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< 1 = String -> Doc
forall a. HasCallStack => String -> a
error "Illegal header (too small)"
          | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 4 = String -> Doc
forall a. HasCallStack => String -> a
error "Illegal header (too large)"          
          | Bool
otherwise = String -> Doc
text (Int -> String
forall a. (Eq a, Num a) => a -> String
hash Int
n)
              where hash :: a -> String
hash 1 = "# "
                    hash 2 = "## "
                    hash 3 = "### "
                    hash 4 = "#### "
                    hash _ = "Illegal header"

{- Will delete it after checking encode works well
-- JSON formatter
formatter :: String -> String
formatter ('"':xs) = '\\' : '"' : formatter xs
formatter ('\\':xs) = '\\' : '\\' : formatter xs
formatter (x:xs) = x: formatter xs
formatter [] = []

jf :: String -> Doc
jf s = text $ replace "`" "\'" (formatter s)
-}

br :: Doc -> Doc
-- | Curly braces.
br :: Doc -> Doc
br x :: Doc
x = String -> Doc
text "{" Doc -> Doc -> Doc
<> Doc
x Doc -> Doc -> Doc
<> String -> Doc
text"}"

mkDiv :: String -> Doc -> Doc -> Doc
mkDiv :: String -> Doc -> Doc -> Doc
mkDiv s :: String
s a0 :: Doc
a0 a1 :: Doc
a1 = (Doc
H.bslash Doc -> Doc -> Doc
<> String -> Doc
text String
s) Doc -> Doc -> Doc
<> Doc -> Doc
br Doc
a0 Doc -> Doc -> Doc
<> Doc -> Doc
br Doc
a1

-- Maybe use "lines" instead (Data.List @lines :: String -> [String])
stripnewLine :: String -> Doc
stripnewLine :: String -> Doc
stripnewLine s :: String
s = [Doc] -> Doc
hcat ((String -> Doc) -> [String] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map String -> Doc
text (String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn "\n" String
s))
--filter (`notElem` "\n" )

makeMetadata :: Doc  
makeMetadata :: Doc
makeMetadata = [Doc] -> Doc
vcat [
  String -> Doc
text " \"metadata\": {", 
  [Doc] -> Doc
vcat[
    String -> Doc
text "  \"kernelspec\": {", 
    String -> Doc
text "   \"display_name\": \"Python 3\",", 
    String -> Doc
text "   \"language\": \"python\",",
    String -> Doc
text "   \"name\": \"python3\"", 
    String -> Doc
text "  },"],
  [Doc] -> Doc
vcat[
    String -> Doc
text "  \"language_info\": {", 
    String -> Doc
text "   \"codemirror_mode\": {", 
    String -> Doc
text "    \"name\": \"ipython\",",
    String -> Doc
text "    \"version\": 3",
    String -> Doc
text "   },"],
  String -> Doc
text "   \"file_extension\": \".py\",", 
  String -> Doc
text "   \"mimetype\": \"text/x-python\",",
  String -> Doc
text "   \"name\": \"python\",",
  String -> Doc
text "   \"nbconvert_exporter\": \"python\",",
  String -> Doc
text "   \"pygments_lexer\": \"ipython3\",",
  String -> Doc
text "   \"version\": \"3.9.1\"",
  String -> Doc
text "  }",
  String -> Doc
text " },",
  String -> Doc
text " \"nbformat\": 4,", 
  String -> Doc
text " \"nbformat_minor\": 4" 
  ]