content: {-# LANGUAGE CPP               #-}
  {-# LANGUAGE OverloadedLists   #-}
  {-# LANGUAGE OverloadedStrings #-}
  module Main
    ( main
    ) where
  
  #ifdef USE_MICROLENS
  import Lens.Micro
  #else
  import Control.Lens
  #endif
  import Data.ByteString.Lazy (ByteString)
  import qualified Data.ByteString.Lazy as LB
  import qualified Data.Map as M
  import Data.Maybe (listToMaybe)
  import Data.Text (Text)
  import qualified StreamTests
  import Text.XML
  
  import Test.Tasty (defaultMain, testGroup)
  import Test.Tasty.HUnit (testCase, (@=?))
  import Test.Tasty.SmallCheck (testProperty)
  
  import TestXlsx
  
  import Codec.Xlsx
  import Codec.Xlsx.Formatted
  
  import AutoFilterTests
  import Common
  import CommonTests
  import CondFmtTests
  import Diff
  import DrawingTests
  import PivotTableTests
  
  main :: IO ()
  main = defaultMain $
    testGroup "Tests"
      [
         testCase "write . read == id" $ do
          let bs = fromXlsx testTime testXlsx
          LB.writeFile "data-test.xlsx" bs
          testXlsx @==? toXlsx (fromXlsx testTime testXlsx)
      ,  testCase "write . fast-read == id" $ do
          let bs = fromXlsx testTime testXlsx
          LB.writeFile "data-test.xlsx" bs
          testXlsx @==? toXlsxFast (fromXlsx testTime testXlsx)
      , testCase "fromRows . toRows == id" $
          testCellMap1 @=? fromRows (toRows testCellMap1)
      , testCase "fromRight . parseStyleSheet . renderStyleSheet == id" $
          testStyleSheet @==? fromRight (parseStyleSheet (renderStyleSheet  testStyleSheet))
      , testCase "correct shared strings parsing" $
          [testSharedStringTable] @=? parseBS testStrings
      , testCase "correct shared strings parsing: single underline" $
          [withSingleUnderline testSharedStringTable] @=? parseBS testStringsWithSingleUnderline
      , testCase "correct shared strings parsing: double underline" $
          [withDoubleUnderline testSharedStringTable] @=? parseBS testStringsWithDoubleUnderline
      , testCase "correct shared strings parsing even when one of the shared strings entry is just <t/>" $
          [testSharedStringTableWithEmpty] @=? parseBS testStringsWithEmpty
      , testCase "correct comments parsing" $
          [testCommentTable] @=? parseBS testComments
      , testCase "correct custom properties parsing" $
          [testCustomProperties] @==? parseBS testCustomPropertiesXml
      , testCase "proper results from `formatted`" $
          testFormattedResult @==? testRunFormatted
      , testCase "proper results from `formatWorkbook`" $
          testFormatWorkbookResult @==? testFormatWorkbook
      , testCase "formatted . toFormattedCells = id" $ do
          let fmtd = formatted testFormattedCells minimalStyleSheet
          testFormattedCells @==? toFormattedCells (formattedCellMap fmtd) (formattedMerges fmtd)
                                                   (formattedStyleSheet fmtd)
      , testCase "proper results from `conditionallyFormatted`" $
          testCondFormattedResult @==? testRunCondFormatted
      , testCase "toXlsxEither: properly formatted" $
          Right testXlsx @==? toXlsxEither (fromXlsx testTime testXlsx)
      , testCase "toXlsxEither: invalid format" $
          Left (InvalidZipArchive "Did not find end of central directory signature") @==? toXlsxEither "this is not a valid XLSX file"
      , testCase "toXlsx: correct floats parsing (typed and untyped cells are floats by default)"
          $ floatsParsingTests toXlsx
      , testCase "toXlsxFast: correct floats parsing (typed and untyped cells are floats by default)"
          $ floatsParsingTests toXlsxFast
      , testCase "toXlsx: correct resolving of absolute relationship targets"
          $ absoluteRelationshipsTest toXlsx
      , testCase "toXlsxFast: correct resolving of absolute relationship targets"
          $ absoluteRelationshipsTest toXlsxFast
      , testGroup "Codec: sheet state visibility"
          [ testGroup "toXlsxEitherFast"
              [ testProperty "pure state == toXlsxEitherFast (fromXlsx (defXlsxWithState state))" $
                  \state ->
                      (Right (Just state) ==) $
                      fmap sheetStateOfDefXlsx $
                      toXlsxEitherFast . fromXlsx testTime $
                      defXlsxWithState state
              , testCase "should otherwise infer visible state by default" $
                  Right (Just Visible) @=? (fmap sheetStateOfDefXlsx . toXlsxEitherFast) (fromXlsx testTime defXlsx)
              ]
          , testGroup "toXlsxEither"
              [ testProperty "pure state == toXlsxEither (fromXlsx (defXlsxWithState state))" $
                  \state ->
                      (Right (Just state) ==) $
                      fmap sheetStateOfDefXlsx $
                      toXlsxEither . fromXlsx testTime $
                      defXlsxWithState state
              , testCase "should otherwise infer visible state by default" $
                  Right (Just Visible) @=? (fmap sheetStateOfDefXlsx . toXlsxEither) (fromXlsx testTime defXlsx)
              ]
          ]
      , CommonTests.tests
      , CondFmtTests.tests
      , PivotTableTests.tests
      , DrawingTests.tests
      , AutoFilterTests.tests
      , StreamTests.tests
      ]
  
  floatsParsingTests :: (ByteString -> Xlsx) -> IO ()
  floatsParsingTests parser = do
    bs <- LB.readFile "data/floats.xlsx"
    let xlsx = parser bs
        parsedCells = maybe mempty (_wsCells . snd) $ listToMaybe $ xlsx ^. xlSheets
        expectedCells = M.fromList
          [ ((1,1), def & cellValue ?~ CellDouble 12.0)
          , ((2,1), def & cellValue ?~ CellDouble 13.0)
          , ((3,1), def & cellValue ?~ CellDouble 14.0 & cellStyle ?~ 1)
          , ((4,1), def & cellValue ?~ CellDouble 15.0)
          ]
    expectedCells @==? parsedCells
  
  -- Test whether absolute logical item names are correctly mapped to ZIP item names.
  -- absolute_relationships.xlsx contains relationships of worksheet, comment,
  -- drawing and pivot table types with absolute paths in their targets.
  absoluteRelationshipsTest :: (ByteString -> Xlsx) -> IO ()
  absoluteRelationshipsTest parser = do
    bs <- LB.readFile "data/absolute_relationships.xlsx"
    let xlsx = parser bs
        expectedComment = Just $ Comment (XlsxText "test comment") "author" False
        parsedComment = xlsx ^? ixSheet "Test" . ixCell (2, 1) . cellComment . _Just
    expectedComment @==? parsedComment
  
  constSheetName :: Text
  constSheetName = "sheet1"
  
  defXlsx :: Xlsx
  defXlsx = def & atSheet constSheetName ?~ def
  
  defXlsxWithState :: SheetState -> Xlsx
  defXlsxWithState state =
      def & atSheet constSheetName ?~ (wsState .~ state $ def)
  
  sheetStateOfDefXlsx :: Xlsx -> Maybe SheetState
  sheetStateOfDefXlsx xlsx =
    xlsx ^. atSheet constSheetName & mapped %~ _wsState
  