{- |
Export table data as OpenDocument Spreadsheet
<https://docs.oasis-open.org/office/OpenDocument/v1.3/>.
This format supports character encodings, fixed header rows and columns,
number formatting, text styles, merged cells, formulas, hyperlinks.
Currently we support Flat ODS, a plain uncompressed XML format.

This is derived from <https://hackage.haskell.org/package/classify-frog-0.2.4.3/src/src/Spreadsheet/Format.hs>

-}
module Hledger.Write.Ods (
    printFods,
    ) where

import Hledger.Write.Spreadsheet (Type(..), Style(..), Emphasis(..), Cell(..))
import Hledger.Data.Types (CommoditySymbol, AmountPrecision(..))
import Hledger.Data.Types (acommodity, aquantity, astyle, asprecision)

import qualified Data.Text.Lazy as TL
import qualified Data.Text as T
import Data.Text (Text)

import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.Foldable (fold)
import Data.Map (Map)
import Data.Set (Set)
import Data.Maybe (mapMaybe)

import qualified System.IO as IO
import Text.Printf (printf)


printFods ::
    IO.TextEncoding ->
    Map Text ((Maybe Int, Maybe Int), [[Cell Text]]) -> TL.Text
printFods :: TextEncoding
-> Map
     CommoditySymbol ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
-> Text
printFods TextEncoding
encoding Map
  CommoditySymbol ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
tables =
    let fileOpen :: [String] -> [String]
fileOpen [String]
customStyles =
          (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map (\Char
c -> case Char
c of Char
'\'' -> Char
'"'; Char
_ -> Char
c)) ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$
          String -> String -> String
forall r. PrintfType r => String -> r
printf String
"<?xml version='1.0' encoding='%s'?>" (TextEncoding -> String
forall a. Show a => a -> String
show TextEncoding
encoding) String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"<office:document" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  office:mimetype='application/vnd.oasis.opendocument.spreadsheet'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  office:version='1.3'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:xsd='http://www.w3.org/2001/XMLSchema'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:text='urn:oasis:names:tc:opendocument:xmlns:text:1.0'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:style='urn:oasis:names:tc:opendocument:xmlns:style:1.0'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:meta='urn:oasis:names:tc:opendocument:xmlns:meta:1.0'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:config='urn:oasis:names:tc:opendocument:xmlns:config:1.0'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:xlink='http://www.w3.org/1999/xlink'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:fo='urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:ooo='http://openoffice.org/2004/office'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:office='urn:oasis:names:tc:opendocument:xmlns:office:1.0'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:table='urn:oasis:names:tc:opendocument:xmlns:table:1.0'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:number='urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:of='urn:oasis:names:tc:opendocument:xmlns:of:1.2'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:field='urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  xmlns:form='urn:oasis:names:tc:opendocument:xmlns:form:1.0'>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"<office:styles>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  <style:style style:name='head' style:family='table-cell'>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <style:paragraph-properties fo:text-align='center'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <style:text-properties fo:font-weight='bold'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  </style:style>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  <style:style style:name='foot' style:family='table-cell'>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <style:text-properties fo:font-weight='bold'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  </style:style>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  <style:style style:name='amount' style:family='table-cell'>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <style:paragraph-properties fo:text-align='end'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  </style:style>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  <style:style style:name='total-amount' style:family='table-cell'>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <style:paragraph-properties fo:text-align='end'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <style:text-properties fo:font-weight='bold'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  </style:style>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  <number:date-style style:name='iso-date'>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <number:year number:style='long'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <number:text>-</number:text>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <number:month number:style='long'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <number:text>-</number:text>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <number:day number:style='long'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  </number:date-style>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  <style:style style:name='date' style:family='table-cell'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"      style:data-style-name='iso-date'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  <style:style style:name='foot-date' style:family='table-cell'" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"      style:data-style-name='iso-date'>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <style:text-properties fo:font-weight='bold'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  </style:style>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          [String]
customStyles [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
          String
"</office:styles>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          []

        fileClose :: [String]
fileClose =
          String
"</office:document>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          []

        tableConfig :: Map t (t t, t t) -> [String]
tableConfig Map t (t t, t t)
tableNames =
          String
" <office:settings>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  <config:config-item-set config:name='ooo:view-settings'>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"   <config:config-item-map-indexed config:name='Views'>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    <config:config-item-map-entry>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"     <config:config-item-map-named config:name='Tables'>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          (Map t [String] -> [String]
forall m. Monoid m => Map t m -> m
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold (Map t [String] -> [String]) -> Map t [String] -> [String]
forall a b. (a -> b) -> a -> b
$
           ((t -> (t t, t t) -> [String])
 -> Map t (t t, t t) -> Map t [String])
-> Map t (t t, t t)
-> (t -> (t t, t t) -> [String])
-> Map t [String]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (t -> (t t, t t) -> [String]) -> Map t (t t, t t) -> Map t [String]
forall k a b. (k -> a -> b) -> Map k a -> Map k b
Map.mapWithKey Map t (t t, t t)
tableNames ((t -> (t t, t t) -> [String]) -> Map t [String])
-> (t -> (t t, t t) -> [String]) -> Map t [String]
forall a b. (a -> b) -> a -> b
$ \t
tableName (t t
mTopRow,t t
mLeftColumn) ->
             String -> t -> String
forall r. PrintfType r => String -> r
printf String
"      <config:config-item-map-entry config:name='%s'>" t
tableName String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
             (((t -> [String]) -> t t -> [String])
-> t t -> (t -> [String]) -> [String]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (t -> [String]) -> t t -> [String]
forall m a. Monoid m => (a -> m) -> t a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap t t
mLeftColumn ((t -> [String]) -> [String]) -> (t -> [String]) -> [String]
forall a b. (a -> b) -> a -> b
$ \t
leftColumn ->
                String
"       <config:config-item config:name='HorizontalSplitMode' config:type='short'>2</config:config-item>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
                String -> t -> String
forall r. PrintfType r => String -> r
printf String
"       <config:config-item config:name='HorizontalSplitPosition' config:type='int'>%d</config:config-item>" t
leftColumn String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
                String -> t -> String
forall r. PrintfType r => String -> r
printf String
"       <config:config-item config:name='PositionRight' config:type='int'>%d</config:config-item>" t
leftColumn String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
                []) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
             (((t -> [String]) -> t t -> [String])
-> t t -> (t -> [String]) -> [String]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (t -> [String]) -> t t -> [String]
forall m a. Monoid m => (a -> m) -> t a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap t t
mTopRow ((t -> [String]) -> [String]) -> (t -> [String]) -> [String]
forall a b. (a -> b) -> a -> b
$ \t
topRow ->
                String
"       <config:config-item config:name='VerticalSplitMode' config:type='short'>2</config:config-item>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
                String -> t -> String
forall r. PrintfType r => String -> r
printf String
"       <config:config-item config:name='VerticalSplitPosition' config:type='int'>%d</config:config-item>" t
topRow String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
                String -> t -> String
forall r. PrintfType r => String -> r
printf String
"       <config:config-item config:name='PositionBottom' config:type='int'>%d</config:config-item>" t
topRow String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
                []) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
             String
"      </config:config-item-map-entry>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
             []) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
          String
"     </config:config-item-map-named>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"    </config:config-item-map-entry>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"   </config:config-item-map-indexed>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"  </config:config-item-set>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
" </office:settings>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          []

        tableOpen :: t -> [String]
tableOpen t
name =
          String
"<office:body>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"<office:spreadsheet>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String -> t -> String
forall r. PrintfType r => String -> r
printf String
"<table:table table:name='%s'>" t
name String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          []

        tableClose :: [String]
tableClose =
          String
"</table:table>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"</office:spreadsheet>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          String
"</office:body>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
          []

    in  [Text] -> Text
TL.unlines ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (String -> Text) -> [String] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (CommoditySymbol -> Text
TL.fromStrict (CommoditySymbol -> Text)
-> (String -> CommoditySymbol) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> CommoditySymbol
T.pack) ([String] -> [Text]) -> [String] -> [Text]
forall a b. (a -> b) -> a -> b
$
        [String] -> [String]
fileOpen
          (let styles :: Set (Emphasis, (CommoditySymbol, AmountPrecision))
styles = [Cell CommoditySymbol]
-> Set (Emphasis, (CommoditySymbol, AmountPrecision))
cellStyles ((((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
 -> [Cell CommoditySymbol])
-> Map
     CommoditySymbol ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
-> [Cell CommoditySymbol]
forall m a. Monoid m => (a -> m) -> Map CommoditySymbol a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ([[Cell CommoditySymbol]] -> [Cell CommoditySymbol]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat([[Cell CommoditySymbol]] -> [Cell CommoditySymbol])
-> (((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
    -> [[Cell CommoditySymbol]])
-> ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
-> [Cell CommoditySymbol]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
-> [[Cell CommoditySymbol]]
forall a b. (a, b) -> b
snd) Map
  CommoditySymbol ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
tables) in
           ((CommoditySymbol, AmountPrecision) -> [String]
numberConfig ((CommoditySymbol, AmountPrecision) -> [String])
-> [(CommoditySymbol, AmountPrecision)] -> [String]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Set (CommoditySymbol, AmountPrecision)
-> [(CommoditySymbol, AmountPrecision)]
forall a. Set a -> [a]
Set.toList (((Emphasis, (CommoditySymbol, AmountPrecision))
 -> (CommoditySymbol, AmountPrecision))
-> Set (Emphasis, (CommoditySymbol, AmountPrecision))
-> Set (CommoditySymbol, AmountPrecision)
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map (Emphasis, (CommoditySymbol, AmountPrecision))
-> (CommoditySymbol, AmountPrecision)
forall a b. (a, b) -> b
snd Set (Emphasis, (CommoditySymbol, AmountPrecision))
styles))
           [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
           ((Emphasis, (CommoditySymbol, AmountPrecision)) -> [String]
cellConfig ((Emphasis, (CommoditySymbol, AmountPrecision)) -> [String])
-> [(Emphasis, (CommoditySymbol, AmountPrecision))] -> [String]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Set (Emphasis, (CommoditySymbol, AmountPrecision))
-> [(Emphasis, (CommoditySymbol, AmountPrecision))]
forall a. Set a -> [a]
Set.toList Set (Emphasis, (CommoditySymbol, AmountPrecision))
styles)) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
        Map CommoditySymbol (Maybe Int, Maybe Int) -> [String]
forall {t :: * -> *} {t :: * -> *} {t} {t} {t}.
(Foldable t, Foldable t, PrintfArg t, PrintfArg t, PrintfArg t) =>
Map t (t t, t t) -> [String]
tableConfig ((((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
 -> (Maybe Int, Maybe Int))
-> Map
     CommoditySymbol ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
-> Map CommoditySymbol (Maybe Int, Maybe Int)
forall a b.
(a -> b) -> Map CommoditySymbol a -> Map CommoditySymbol b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
-> (Maybe Int, Maybe Int)
forall a b. (a, b) -> a
fst Map
  CommoditySymbol ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
tables) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
        (Map
  CommoditySymbol ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
-> [(CommoditySymbol,
     ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]]))]
forall k a. Map k a -> [(k, a)]
Map.toAscList Map
  CommoditySymbol ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]])
tables [(CommoditySymbol,
  ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]]))]
-> ((CommoditySymbol,
     ((Maybe Int, Maybe Int), [[Cell CommoditySymbol]]))
    -> [String])
-> [String]
forall a b. [a] -> (a -> [b]) -> [b]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \(CommoditySymbol
name,((Maybe Int, Maybe Int)
_,[[Cell CommoditySymbol]]
table)) ->
            CommoditySymbol -> [String]
forall {t}. PrintfArg t => t -> [String]
tableOpen CommoditySymbol
name [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
            ([[Cell CommoditySymbol]]
table [[Cell CommoditySymbol]]
-> ([Cell CommoditySymbol] -> [String]) -> [String]
forall a b. [a] -> (a -> [b]) -> [b]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[Cell CommoditySymbol]
row ->
                String
"<table:table-row>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
                ([Cell CommoditySymbol]
row [Cell CommoditySymbol]
-> (Cell CommoditySymbol -> [String]) -> [String]
forall a b. [a] -> (a -> [b]) -> [b]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Cell CommoditySymbol -> [String]
formatCell) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
                String
"</table:table-row>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
                []) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
            [String]
tableClose) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
        [String]
fileClose


cellStyles :: [Cell Text] -> Set (Emphasis, (CommoditySymbol, AmountPrecision))
cellStyles :: [Cell CommoditySymbol]
-> Set (Emphasis, (CommoditySymbol, AmountPrecision))
cellStyles =
    [(Emphasis, (CommoditySymbol, AmountPrecision))]
-> Set (Emphasis, (CommoditySymbol, AmountPrecision))
forall a. Ord a => [a] -> Set a
Set.fromList ([(Emphasis, (CommoditySymbol, AmountPrecision))]
 -> Set (Emphasis, (CommoditySymbol, AmountPrecision)))
-> ([Cell CommoditySymbol]
    -> [(Emphasis, (CommoditySymbol, AmountPrecision))])
-> [Cell CommoditySymbol]
-> Set (Emphasis, (CommoditySymbol, AmountPrecision))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    (Cell CommoditySymbol
 -> Maybe (Emphasis, (CommoditySymbol, AmountPrecision)))
-> [Cell CommoditySymbol]
-> [(Emphasis, (CommoditySymbol, AmountPrecision))]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\Cell CommoditySymbol
cell ->
        case Cell CommoditySymbol -> Type
forall text. Cell text -> Type
cellType Cell CommoditySymbol
cell of
            TypeAmount Amount
amt ->
                (Emphasis, (CommoditySymbol, AmountPrecision))
-> Maybe (Emphasis, (CommoditySymbol, AmountPrecision))
forall a. a -> Maybe a
Just
                    (case Cell CommoditySymbol -> Style
forall text. Cell text -> Style
cellStyle Cell CommoditySymbol
cell of
                        Body Emphasis
emph -> Emphasis
emph
                        Style
Head -> Emphasis
Total,
                     (Amount -> CommoditySymbol
acommodity Amount
amt, AmountStyle -> AmountPrecision
asprecision (AmountStyle -> AmountPrecision) -> AmountStyle -> AmountPrecision
forall a b. (a -> b) -> a -> b
$ Amount -> AmountStyle
astyle Amount
amt))
            Type
_ -> Maybe (Emphasis, (CommoditySymbol, AmountPrecision))
forall a. Maybe a
Nothing)

numberStyleName :: (CommoditySymbol, AmountPrecision) -> String
numberStyleName :: (CommoditySymbol, AmountPrecision) -> String
numberStyleName (CommoditySymbol
comm, AmountPrecision
prec) =
    String -> CommoditySymbol -> String -> String
forall r. PrintfType r => String -> r
printf String
"%s-%s" CommoditySymbol
comm (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$
    case AmountPrecision
prec of
        AmountPrecision
NaturalPrecision -> String
"natural"
        Precision Word8
k -> Word8 -> String
forall a. Show a => a -> String
show Word8
k

numberConfig :: (CommoditySymbol, AmountPrecision) -> [String]
numberConfig :: (CommoditySymbol, AmountPrecision) -> [String]
numberConfig (CommoditySymbol
comm, AmountPrecision
prec) =
    let precStr :: String
precStr =
            case AmountPrecision
prec of
                AmountPrecision
NaturalPrecision -> String
""
                Precision Word8
k -> String -> Word8 -> String
forall r. PrintfType r => String -> r
printf String
" number:decimal-places='%d'" Word8
k
        name :: String
name = (CommoditySymbol, AmountPrecision) -> String
numberStyleName (CommoditySymbol
comm, AmountPrecision
prec)
    in
    String -> String -> String
forall r. PrintfType r => String -> r
printf String
"  <number:number-style style:name='number-%s'>" String
name String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
    String -> String -> String
forall r. PrintfType r => String -> r
printf String
"    <number:number number:min-integer-digits='1'%s/>" String
precStr String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
    String -> String -> CommoditySymbol -> String
forall r. PrintfType r => String -> r
printf String
"    <number:text>%s%s</number:text>"
      (if CommoditySymbol -> Bool
T.null CommoditySymbol
comm then String
"" else String
" ") CommoditySymbol
comm String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
    String
"  </number:number-style>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
    []

emphasisName :: Emphasis -> String
emphasisName :: Emphasis -> String
emphasisName Emphasis
emph =
    case Emphasis
emph of
        Emphasis
Item -> String
"item"
        Emphasis
Total -> String
"total"

cellConfig :: (Emphasis, (CommoditySymbol, AmountPrecision)) -> [String]
cellConfig :: (Emphasis, (CommoditySymbol, AmountPrecision)) -> [String]
cellConfig (Emphasis
emph, (CommoditySymbol, AmountPrecision)
numParam) =
    let name :: String
name = (CommoditySymbol, AmountPrecision) -> String
numberStyleName (CommoditySymbol, AmountPrecision)
numParam in
    let style :: String
        style :: String
style =
            String -> String -> String -> String -> String
forall r. PrintfType r => String -> r
printf String
"style:name='%s-%s' style:data-style-name='number-%s'"
                (Emphasis -> String
emphasisName Emphasis
emph) String
name String
name in
    case Emphasis
emph of
        Emphasis
Item ->
            String -> String -> String
forall r. PrintfType r => String -> r
printf String
"  <style:style style:family='table-cell' %s/>" String
style String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
            []
        Emphasis
Total ->
            String -> String -> String
forall r. PrintfType r => String -> r
printf String
"  <style:style style:family='table-cell' %s>" String
style String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
            String
"    <style:text-properties fo:font-weight='bold'/>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
            String
"  </style:style>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
            []


formatCell :: Cell Text -> [String]
formatCell :: Cell CommoditySymbol -> [String]
formatCell Cell CommoditySymbol
cell =
    let style, valueType :: String
        style :: String
style =
          case (Cell CommoditySymbol -> Style
forall text. Cell text -> Style
cellStyle Cell CommoditySymbol
cell, Cell CommoditySymbol -> Type
forall text. Cell text -> Type
cellType Cell CommoditySymbol
cell) of
            (Body Emphasis
emph, TypeAmount Amount
amt) -> String -> String
tableStyle (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Emphasis -> Amount -> String
forall {t}. PrintfType t => Emphasis -> Amount -> t
numberStyle Emphasis
emph Amount
amt
            (Body Emphasis
Item, Type
TypeString) -> String
""
            (Body Emphasis
Item, Type
TypeMixedAmount) -> String -> String
tableStyle String
"amount"
            (Body Emphasis
Item, Type
TypeDate) -> String -> String
tableStyle String
"date"
            (Body Emphasis
Total, Type
TypeString) -> String -> String
tableStyle String
"foot"
            (Body Emphasis
Total, Type
TypeMixedAmount) -> String -> String
tableStyle String
"total-amount"
            (Body Emphasis
Total, Type
TypeDate) -> String -> String
tableStyle String
"foot-date"
            (Style
Head, Type
_) -> String -> String
tableStyle String
"head"
        numberStyle :: Emphasis -> Amount -> t
numberStyle Emphasis
emph Amount
amt =
            String -> String -> String -> t
forall r. PrintfType r => String -> r
printf String
"%s-%s"
                (Emphasis -> String
emphasisName Emphasis
emph)
                ((CommoditySymbol, AmountPrecision) -> String
numberStyleName (Amount -> CommoditySymbol
acommodity Amount
amt, AmountStyle -> AmountPrecision
asprecision (AmountStyle -> AmountPrecision) -> AmountStyle -> AmountPrecision
forall a b. (a -> b) -> a -> b
$ Amount -> AmountStyle
astyle Amount
amt))
        tableStyle :: String -> String
tableStyle = String -> String -> String
forall r. PrintfType r => String -> r
printf String
" table:style-name='%s'"

        valueType :: String
valueType =
            case Cell CommoditySymbol -> Type
forall text. Cell text -> Type
cellType Cell CommoditySymbol
cell of
                TypeAmount Amount
amt ->
                    String -> String -> String
forall r. PrintfType r => String -> r
printf
                        String
"office:value-type='float' office:value='%s'"
                        (Quantity -> String
forall a. Show a => a -> String
show (Quantity -> String) -> Quantity -> String
forall a b. (a -> b) -> a -> b
$ Amount -> Quantity
aquantity Amount
amt)
                Type
TypeDate ->
                    String -> CommoditySymbol -> String
forall r. PrintfType r => String -> r
printf
                        String
"office:value-type='date' office:date-value='%s'"
                        (Cell CommoditySymbol -> CommoditySymbol
forall text. Cell text -> text
cellContent Cell CommoditySymbol
cell)
                Type
_ -> String
"office:value-type='string'"

    in
    String -> String -> String -> String
forall r. PrintfType r => String -> r
printf String
"<table:table-cell%s %s>" String
style String
valueType String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
    String -> String -> String
forall r. PrintfType r => String -> r
printf String
"<text:p>%s</text:p>" (String -> String
escape (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ CommoditySymbol -> String
T.unpack (CommoditySymbol -> String) -> CommoditySymbol -> String
forall a b. (a -> b) -> a -> b
$ Cell CommoditySymbol -> CommoditySymbol
forall text. Cell text -> text
cellContent Cell CommoditySymbol
cell) String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
    String
"</table:table-cell>" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
    []

escape :: String -> String
escape :: String -> String
escape =
    (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((Char -> String) -> String -> String)
-> (Char -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ \Char
c ->
        case Char
c of
            Char
'\n' -> String
"&#10;"
            Char
'&' -> String
"&amp;"
            Char
'<' -> String
"&lt;"
            Char
'>' -> String
"&gt;"
            Char
'"' -> String
"&quot;"
            Char
'\'' -> String
"&apos;"
            Char
_ -> [Char
c]