getOutputSection
  :: FilePath -> Bool -> Maybe T.Text -> Int -> [(T.Text, T.Text)] -> Section
  -> IO (OutputSection, Bool)
getOutputSection inputWrapperPath isRoot numberSoFar nextNumberPart titleSoFar
                 section = do
  let number =
        if isRoot
          then Nothing
          else case sectionType section of
                 Numbered ->
                   Just $ T.concat [fromMaybe "" numberSoFar,
                                    T.pack $ show nextNumberPart,
                                    "."]
                 Lettered ->
                   Just $ T.concat
                     [fromMaybe "" numberSoFar,
                      T.pack [chr (ord 'A' + nextNumberPart - 1)],
                      "."]
                 Anonymous -> Nothing
                 InParent _ -> Nothing
      identifier = computeIdentifierHash $ sectionDocumentID section
      finalTitleComponent =
        case sectionPath section of
          [] -> Nothing
          path -> Just (identifier, snd $ last path)
      initialTitle =
        case sectionType section of
          InParent False -> Nothing
          InParent True -> fmap (\item -> [item]) finalTitleComponent
          Anonymous -> Just titleSoFar
          _ -> case titleSoFar ++ maybeToList finalTitleComponent of
                 [] -> Nothing
                 result -> Just result
      properTitle =
        case sectionType section of
          Anonymous -> fmap snd finalTitleComponent
          _ -> Nothing
      inParent =
        case sectionType section of
          InParent _ -> True
          _ -> False
      childNumber =
        if inParent
          then numberSoFar
          else number
  (_, _, title, children, body) <-
        foldM (\(indexSoFar, letteredModeSoFar, titleSoFar, childrenSoFar,
                 bodySoFar)
                childSection -> do
                  let (indexHere, letteredMode) =
                        case sectionType childSection of
                          Lettered -> if letteredModeSoFar
                                        then (indexSoFar, True)
                                        else (1, True)
                          _ -> (indexSoFar, letteredModeSoFar)
                  (child, childInLine) <-
                    getOutputSection inputWrapperPath
                                     False
                                     childNumber
                                     indexHere
                                     (fromMaybe [] titleSoFar)
                                     childSection
                  let title =
                        case titleSoFar of
                          Just _ -> titleSoFar
                          Nothing -> if childInLine
                                       then outputSectionTitle child
                                       else Nothing
                      body = bodySoFar ++ outputSectionParentBody child
                      children =
                        if childInLine
                          then childrenSoFar
                          else childrenSoFar ++ [child]
                      index =
                        if childInLine
                          then indexHere
                          else indexHere + 1
                  return $!! (index, letteredMode, title, children, body))
              (1, False, initialTitle, [], [])
              (sectionChildren section)
  let bodyPrefix =
        if inParent
          then case title of
                 Nothing -> []
                 Just title ->
                   [Header
                     $ concat [map (\(identifier, name) ->
                                      Link identifier [Text name])
                                   (init title),
                               [Text $ snd $ last title]]]
          else []
      parentBody =
        case (number, finalTitleComponent) of
          (Just number, Just (_, title)) ->
            [Header [Link identifier [Text number, Text " ", Text title]]]
          (Just number, Nothing) ->
            [Header [Link identifier [Text number]]]
          (Nothing, Just (_, title)) ->
            [Header [Link identifier [Text title]]]
          (Nothing, Nothing) ->
            [Header [Link identifier [Text "?"]]]
  putStrLn $ "Processing "
             ++ (case number of
                   Nothing -> ""
                   Just number -> T.unpack number ++ " ")
             ++ (case title of
                   Nothing -> "(Untitled)"
                   Just title -> T.unpack $ T.intercalate titleSeparator
                                                          $ map snd title)
             ++ (case properTitle of
                   Nothing -> ""
                   Just properTitle ->
                     T.unpack titleSeparator ++ T.unpack properTitle)
             ++ "..."
  bodyMain <- getSectionBody inputWrapperPath (sectionDocumentID section)
  return $!! (OutputSection {
                  outputSectionID = identifier,
                  outputSectionNumber = number,
                  outputSectionTitle = title,
                  outputSectionProperTitle = properTitle,
                  outputSectionParentBody =
                    if inParent
                      then bodyPrefix ++ bodyMain ++ body
                      else parentBody,
                  outputSectionSelfBody =
                    if inParent
                      then []
                      else bodyPrefix ++ bodyMain ++ body,
                  outputSectionChildren = children
               }, inParent)
getOutputSection
  :: FilePath -> Bool -> Maybe T.Text -> Int -> [(T.Text, T.Text)] -> Section
  -> IO (OutputSection, Bool)
getOutputSection inputWrapperPath isRoot numberSoFar nextNumberPart titleSoFar
                 section = do
  let number =
        if isRoot
          then Nothing
          else case sectionType section of
                 Numbered ->
                   Just $ T.concat [fromMaybe "" numberSoFar,
                                    T.pack $ show nextNumberPart,
                                    "."]
                 Lettered ->
                   Just $ T.concat
                     [fromMaybe "" numberSoFar,
                      T.pack [chr (ord 'A' + nextNumberPart - 1)],
                      "."]
                 Anonymous -> Nothing
                 InParent _ -> Nothing
      identifier = computeIdentifierHash $ sectionDocumentID section
      finalTitleComponent =
        case sectionPath section of
          [] -> Nothing
          path -> Just (identifier, snd $ last path)
      initialTitle =
        case sectionType section of
          InParent False -> Nothing
          InParent True -> fmap (\item -> [item]) finalTitleComponent
          Anonymous -> Just titleSoFar
          _ -> case titleSoFar ++ maybeToList finalTitleComponent of
                 [] -> Nothing
                 result -> Just result
      properTitle =
        case sectionType section of
          Anonymous -> fmap snd finalTitleComponent
          _ -> Nothing
      inParent =
        case sectionType section of
          InParent _ -> True
          _ -> False
      childNumber =
        if inParent
          then numberSoFar
          else number
  (_, _, title, children, body) <-
        foldM (\(indexSoFar, letteredModeSoFar, titleSoFar, childrenSoFar,
                 bodySoFar)
                childSection -> do
                  let (indexHere, letteredMode) =
                        case sectionType childSection of
                          Lettered -> if letteredModeSoFar
                                        then (indexSoFar, True)
                                        else (1, True)
                          _ -> (indexSoFar, letteredModeSoFar)
                  (child, childInLine) <-
                    getOutputSection inputWrapperPath
                                     False
                                     childNumber
                                     indexHere
                                     (fromMaybe [] titleSoFar)
                                     childSection
                  let title =
                        case titleSoFar of
                          Just _ -> titleSoFar
                          Nothing -> if childInLine
                                       then outputSectionTitle child
                                       else Nothing
                      body = bodySoFar ++ outputSectionParentBody child
                      children =
                        if childInLine
                          then childrenSoFar
                          else childrenSoFar ++ [child]
                      index =
                        if childInLine
                          then indexHere
                          else indexHere + 1
                  return $!! (index, letteredMode, title, children, body))
              (1, False, initialTitle, [], [])
              (sectionChildren section)
  let bodyPrefix =
        if inParent
          then case title of
                 Nothing -> []
                 Just title ->
                   [Header
                     $ concat [map (\(identifier, name) ->
                                      Link identifier [Text name])
                                   (init title),
                               [Text $ snd $ last title]]]
          else []
      parentBody =
        case (number, finalTitleComponent) of
          (Just number, Just (_, title)) ->
            [Header [Link identifier [Text number, Text " ", Text title]]]
          (Just number, Nothing) ->
            [Header [Link identifier [Text number]]]
          (Nothing, Just (_, title)) ->
            [Header [Link identifier [Text title]]]
          (Nothing, Nothing) ->
            [Header [Link identifier [Text "?"]]]
  putStrLn $ "Processing "
             ++ (case number of
                   Nothing -> ""
                   Just number -> T.unpack number ++ " ")
             ++ (case title of
                   Nothing -> "(Untitled)"
                   Just title -> T.unpack $ T.intercalate titleSeparator
                                                          $ map snd title)
             ++ (case properTitle of
                   Nothing -> ""
                   Just properTitle ->
                     T.unpack titleSeparator ++ T.unpack properTitle)
             ++ "..."
  bodyMain <- getSectionBody inputWrapperPath (sectionDocumentID section)
  return $!! (OutputSection {
                  outputSectionID = identifier,
                  outputSectionNumber = number,
                  outputSectionTitle = title,
                  outputSectionProperTitle = properTitle,
                  outputSectionParentBody =
                    if inParent
                      then bodyPrefix ++ bodyMain ++ body
                      else parentBody,
                  outputSectionSelfBody =
                    if inParent
                      then []
                      else bodyPrefix ++ bodyMain ++ body,
                  outputSectionChildren = children
               }, inParent)
getOutputSection inputWrapperPath isRoot numberSoFar nextNumberPart titleSoFar
                 section = do
  let number =
        if isRoot
          then Nothing
          else case sectionType section of
                 Numbered ->
                   Just $ T.concat [fromMaybe "" numberSoFar,
                                    T.pack $ show nextNumberPart,
                                    "."]
                 Lettered ->
                   Just $ T.concat
                     [fromMaybe "" numberSoFar,
                      T.pack [chr (ord 'A' + nextNumberPart - 1)],
                      "."]
                 Anonymous -> Nothing
                 InParent _ -> Nothing
      identifier = computeIdentifierHash $ sectionDocumentID section
      finalTitleComponent =
        case sectionPath section of
          [] -> Nothing
          path -> Just (identifier, snd $ last path)
      initialTitle =
        case sectionType section of
          InParent False -> Nothing
          InParent True -> fmap (\item -> [item]) finalTitleComponent
          Anonymous -> Just titleSoFar
          _ -> case titleSoFar ++ maybeToList finalTitleComponent of
                 [] -> Nothing
                 result -> Just result
      properTitle =
        case sectionType section of
          Anonymous -> fmap snd finalTitleComponent
          _ -> Nothing
      inParent =
        case sectionType section of
          InParent _ -> True
          _ -> False
      childNumber =
        if inParent
          then numberSoFar
          else number
  (_, _, title, children, body) <-
        foldM (\(indexSoFar, letteredModeSoFar, titleSoFar, childrenSoFar,
                 bodySoFar)
                childSection -> do
                  let (indexHere, letteredMode) =
                        case sectionType childSection of
                          Lettered -> if letteredModeSoFar
                                        then (indexSoFar, True)
                                        else (1, True)
                          _ -> (indexSoFar, letteredModeSoFar)
                  (child, childInLine) <-
                    getOutputSection inputWrapperPath
                                     False
                                     childNumber
                                     indexHere
                                     (fromMaybe [] titleSoFar)
                                     childSection
                  let title =
                        case titleSoFar of
                          Just _ -> titleSoFar
                          Nothing -> if childInLine
                                       then outputSectionTitle child
                                       else Nothing
                      body = bodySoFar ++ outputSectionParentBody child
                      children =
                        if childInLine
                          then childrenSoFar
                          else childrenSoFar ++ [child]
                      index =
                        if childInLine
                          then indexHere
                          else indexHere + 1
                  return $!! (index, letteredMode, title, children, body))
              (1, False, initialTitle, [], [])
              (sectionChildren section)
  let bodyPrefix =
        if inParent
          then case title of
                 Nothing -> []
                 Just title ->
                   [Header
                     $ concat [map (\(identifier, name) ->
                                      Link identifier [Text name])
                                   (init title),
                               [Text $ snd $ last title]]]
          else []
      parentBody =
        case (number, finalTitleComponent) of
          (Just number, Just (_, title)) ->
            [Header [Link identifier [Text number, Text " ", Text title]]]
          (Just number, Nothing) ->
            [Header [Link identifier [Text number]]]
          (Nothing, Just (_, title)) ->
            [Header [Link identifier [Text title]]]
          (Nothing, Nothing) ->
            [Header [Link identifier [Text "?"]]]
  putStrLn $ "Processing "
             ++ (case number of
                   Nothing -> ""
                   Just number -> T.unpack number ++ " ")
             ++ (case title of
                   Nothing -> "(Untitled)"
                   Just title -> T.unpack $ T.intercalate titleSeparator
                                                          $ map snd title)
             ++ (case properTitle of
                   Nothing -> ""
                   Just properTitle ->
                     T.unpack titleSeparator ++ T.unpack properTitle)
             ++ "..."
  bodyMain <- getSectionBody inputWrapperPath (sectionDocumentID section)
  return $!! (OutputSection {
                  outputSectionID = identifier,
                  outputSectionNumber = number,
                  outputSectionTitle = title,
                  outputSectionProperTitle = properTitle,
                  outputSectionParentBody =
                    if inParent
                      then bodyPrefix ++ bodyMain ++ body
                      else parentBody,
                  outputSectionSelfBody =
                    if inParent
                      then []
                      else bodyPrefix ++ bodyMain ++ body,
                  outputSectionChildren = children
               }, inParent)