module VerifyUsingMockTerminal where

import Verify.Graphics.Vty.Prelude

import Verify.Graphics.Vty.Picture
import Verify.Graphics.Vty.Image
import Verify.Graphics.Vty.Attributes
import Verify.Graphics.Vty.Span
import Verify.Graphics.Vty.Output
import Graphics.Vty.Output
import Graphics.Vty.Output.Interface
import Graphics.Vty.Output.Mock

import Graphics.Vty.Debug

import Verify

import qualified Data.ByteString as BS
import Data.IORef
import qualified Data.String.UTF8 as UTF8

import System.IO

unitImageUnitBounds :: UnitImage -> Property
unitImageUnitBounds (UnitImage _ i) = liftIOResult $ do
    (_,t) <- mockTerminal (1,1)
    dc <- displayBounds t >>= displayContext t
    let pic = picForImage i
    outputPicture dc pic
    return succeeded

unitImageArbBounds :: UnitImage -> MockWindow -> Property
unitImageArbBounds (UnitImage _ i) (MockWindow w h) = liftIOResult $ do
    (_,t) <- mockTerminal (w,h)
    dc <- displayBounds t >>= displayContext t
    let pic = picForImage i
    outputPicture dc pic
    return succeeded

singleTRow :: MockWindow -> Property
singleTRow (MockWindow w h) = liftIOResult $ do
    (mockData,t) <- mockTerminal (w,h)
    dc <- displayBounds t >>= displayContext t
    -- create an image that contains just the character T repeated for a
    -- single row
    let i = horizCat $ replicate (fromEnum w) (char defAttr 'T')
        pic = (picForImage i) { picBackground = Background 'B' defAttr }
    outputPicture dc pic
    -- The mock output string that represents the output bytes a single
    -- line containing the T string: Followed by h - 1 lines of a change
    -- to the background attribute and then the background character
    let expected = "H" ++ "MDA" ++ replicate (fromEnum w) 'T'
                 ++ concat (replicate (fromEnum h - 1) $ "MDA" ++ replicate (fromEnum w) 'B')
    compareMockOutput mockData expected

manyTRows :: MockWindow -> Property
manyTRows (MockWindow w h) = liftIOResult $ do
    (mockData, t) <- mockTerminal (w,h)
    dc <- displayBounds t >>= displayContext t
    -- create an image that contains the character 'T' repeated for all
    -- the rows
    let i = vertCat $ replicate (fromEnum h) $ horizCat $ replicate (fromEnum w) (char defAttr 'T')
        pic = (picForImage i) { picBackground = Background 'B' defAttr }
    outputPicture dc pic
    -- The UTF8 string that represents the output bytes is h repeats of
    -- a move, 'M', followed by an attribute change. 'A', followed by w
    -- 'T's
    let expected = "H" ++ concat (replicate (fromEnum h) $ "MDA" ++ replicate (fromEnum w) 'T')
    compareMockOutput mockData expected

manyTRowsCroppedWidth :: MockWindow -> Property
manyTRowsCroppedWidth (MockWindow w h) = liftIOResult $ do
    (mockData,t) <- mockTerminal (w,h)
    dc <- displayBounds t >>= displayContext t
    -- create an image that contains the character 'T' repeated for all
    -- the rows
    let i = vertCat $ replicate (fromEnum h) $ horizCat $ replicate (fromEnum w * 2) (char defAttr 'T')
        pic = (picForImage i) { picBackground = Background 'B' defAttr }
    outputPicture dc pic
    -- The UTF8 string that represents the output bytes is h repeats of
    -- a move, 'M', followed by an attribute change. 'A', followed by w
    -- 'T's
    let expected = "H" ++ concat (replicate (fromEnum h) $ "MDA" ++ replicate (fromEnum w) 'T')
    compareMockOutput mockData expected

manyTRowsCroppedHeight :: MockWindow -> Property
manyTRowsCroppedHeight (MockWindow w h) = liftIOResult $ do
    (mockData,t) <- mockTerminal (w,h)
    dc <- displayBounds t >>= displayContext t
    -- create an image that contains the character 'T' repeated for all
    -- the rows
    let i = vertCat $ replicate (fromEnum h * 2) $ horizCat $ replicate (fromEnum w) (char defAttr 'T')
        pic = (picForImage i) { picBackground = Background 'B' defAttr }
    outputPicture dc pic
    -- The UTF8 string that represents the output bytes is h repeats of
    -- a move, 'M', followed by an attribute change. 'A', followed by w
    -- count 'T's
    let expected = "H" ++ concat (replicate (fromEnum h) $ "MDA" ++ replicate (fromEnum w) 'T')
    compareMockOutput mockData expected

tests :: IO [Test]
tests = return [ verify "unitImageUnitBounds" unitImageUnitBounds
               , verify "unitImageArbBounds" unitImageArbBounds
               , verify "singleTRow" singleTRow
               , verify "manyTRows" manyTRows
               , verify "manyTRowsCroppedWidth" manyTRowsCroppedWidth
               , verify "manyTRowsCroppedHeight" manyTRowsCroppedHeight
               ]
