content: {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE QuasiQuotes #-}
  {-# LANGUAGE RecordWildCards #-}
  {-# LANGUAGE NoImplicitPrelude #-}
  
  -- |
  -- Module      : $header$
  -- Copyright   : (c) Laurent P René de Cotret, 2019 - present
  -- License     : GNU GPL, version 2 or above
  -- Maintainer  : laurent.decotret@outlook.com
  -- Stability   : internal
  -- Portability : portable
  --
  -- Rendering Matplotlib code blocks.
  --
  -- Note that the MatplotlibM renderer supports two extra arguments:
  --     * @tight_bbox=True|False@ : Make plot bounding box tight. Default is False
  --     * @transparent=True|False@ : Make plot background transparent (perfect for web pages). Default is False.
  module Text.Pandoc.Filter.Plot.Renderers.Matplotlib
    ( matplotlib,
      matplotlibSupportedSaveFormats,
    )
  where
  
  import qualified Data.Map.Strict as M
  import Data.Monoid (Any (..))
  import qualified Data.Text as T
  import Text.Pandoc.Filter.Plot.Renderers.Prelude
  
  matplotlib :: PlotM Renderer
  matplotlib = do
    cmdargs <- asksConfig matplotlibCmdArgs
    return
      $ Renderer
        { rendererToolkit = Matplotlib,
          rendererCapture = matplotlibCapture,
          rendererCommand = matplotlibCommand cmdargs,
          rendererAvailability = CommandSuccess $ \exe -> [st|#{pathToExe exe} -c "import matplotlib"|],
          rendererSupportedSaveFormats = matplotlibSupportedSaveFormats,
          rendererChecks = [matplotlibCheckIfShow],
          rendererLanguage = "python",
          rendererComment = mappend "# ",
          rendererScriptExtension = ".py"
        }
  
  matplotlibSupportedSaveFormats :: [SaveFormat]
  matplotlibSupportedSaveFormats = [PNG, PDF, SVG, JPG, EPS, TIF]
  
  matplotlibCommand :: Text -> OutputSpec -> Text
  matplotlibCommand cmdargs OutputSpec {..} = [st|#{pathToExe oExecutable} #{cmdargs} "#{oScriptPath}"|]
  
  matplotlibCapture :: FigureSpec -> FilePath -> Script
  matplotlibCapture = appendCapture matplotlibCaptureFragment
  
  matplotlibCaptureFragment :: FigureSpec -> FilePath -> Script
  matplotlibCaptureFragment FigureSpec {..} fname =
    [st|
  import matplotlib.pyplot as plt
  plt.savefig(r"#{fname}", dpi=#{dpi}, transparent=#{transparent}, bbox_inches=#{tightBox})
  |]
    where
      attrs = M.fromList extraAttrs
      tight_ = readBool $ M.findWithDefault "False" (T.pack $ show MatplotlibTightBBoxK) attrs
      transparent_ = readBool $ M.findWithDefault "False" (T.pack $ show MatplotlibTransparentK) attrs
      tightBox = if tight_ then ("'tight'" :: Text) else ("None" :: Text)
      transparent = if transparent_ then ("True" :: Text) else ("False" :: Text)
  
  -- | Check if `matplotlib.pyplot.show()` calls are present in the script,
  -- which would halt pandoc-plot
  matplotlibCheckIfShow :: Script -> CheckResult
  matplotlibCheckIfShow s =
    if getAny $ mconcat showPresent
      then CheckFailed "encountered a call to `matplotlib.pyplot.show` or `plt.show`, which would stall `pandoc-plot"
      else CheckPassed
    where
      showPresent =
        (\n -> Any (T.isInfixOf n s))
          <$> [ "matplotlib.pyplot.show()",
                "pyplot.show()",
                "plt.show()"
              ]
  
  -- | Flexible boolean parsing
  readBool :: Text -> Bool
  readBool s
    | s `elem` ["True", "true", "'True'", "'true'", "1"] = True
    | s `elem` ["False", "false", "'False'", "'false'", "0"] = False
    | otherwise = errorWithoutStackTrace $ unpack $ mconcat ["Could not parse '", s, "' into a boolean. Please use 'True' or 'False'"]
  