module WaveFileTests where

import HUnit
import qualified Data.ByteString.Lazy as BS
import qualified Data.ByteString.Lazy.Char8 as C
import Data.SoundFile
import Data.SoundFile.WaveFile
import Data.Binary (encode, decode)

riffBS = C.pack "RIFF"
waveBS = C.pack "WAVE"

--various ByteStrings for testing purposes
validHeader = SndFileInfo 2 44100 16
validFormatChunk = WaveFormat (SndFileInfo 2 44100 16)
validDataChunk = WaveData (BS.drop 8 validDataChunkBS) 8
validFormatChunkBS =    BS.pack headerlist
                        where headerlist = [102,109,116,32 , 16,0,0,0 , 1,0 , 2,0 , 68,172,0,0 , 16,177,2,0 , 4,0 , 16,0 ]
invalidChunkBS = BS.pack [13,14,15,16,17,17,17,17]
nonPcmChunkBS = BS.pack [102,109,116,32, 16,0,0,0, 2,0, 2,0, 68,172,0,0, 16,177,2,0, 4,0, 16,0]
validDataChunkBS = BS.pack [100,97,116,97, 8,0,0,0, 1,2,3,4, 5,6,7,8]
shortDataChunkBS = BS.pack [100,97,116,97, 8,0,0,0, 1,2,3,4] --too short for the specified length
longDataChunkBS = BS.pack [100,97,116,97, 8,0,0,0, 1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16]
validWaveHeaderBS = BS.concat [riffBS, BS.pack [44,0,0,0], waveBS]

--various WaveFiles for testing purposes
emptyWaveFile = WaveFile validFormatChunk []
baseWaveFile = WaveFile validFormatChunk [validDataChunk]
base2WaveFile = WaveFile validFormatChunk [validDataChunk, validDataChunk]

--all the tests in this module
allTests = TestList $ concat [getWaveFileTests, encodeTests, binTests]

--test WaveChunk get
gCTest1 = TestCase (assertEqual "get valid header" validFormatChunk (decode validFormatChunkBS))
gCTest2 = TestCase (assertEqual "get invalid header" validFormatChunk (decode invalidChunkBS)) --fails with exception, I need exception handling.
gCTest3 = TestCase (assertEqual "get valid data" validDataChunk (decode validDataChunkBS))
gCTest4 = TestCase (assertEqual "get invalid data" validDataChunk (decode shortDataChunkBS)) --fails, no error testing.

--test WaveChunk put
pCTest1 = TestCase (assertEqual "get valid header" validFormatChunkBS (encode validFormatChunk))
pCTest2 = TestCase (assertEqual "get valid data" validDataChunkBS (encode validDataChunk))

binTests = [TestLabel "get valid header" gCTest1,
               -- TestLabel "get invalid header" gCTest2,
                TestLabel "get valid data" gCTest3,
                --TestLabel "get invalid data" gCTest4,
                TestLabel "put valid header" pCTest1,
                TestLabel "put valid data" pCTest2]


--test encodeHeader
ecHeadTest1 = TestCase $ assertEqual "encodeHeader valid header" validFormatChunkBS (encode $ WaveFormat validHeader)

encodeTests = [TestLabel "encodeHeader valid header" ecHeadTest1]

--test getWaveFile
wavTest1 = TestCase(assertEqual "getWaveFile null" Nothing (getWaveFile BS.empty))
wavTest2 = TestCase(assertEqual "getWaveFile invalid" Nothing (getWaveFile $ BS.concat [validWaveHeaderBS, invalidChunkBS]))
wavTest3 = TestCase(assertEqual "getWaveFile header only" (Just emptyWaveFile) (getWaveFile $ BS.concat [validWaveHeaderBS, validFormatChunkBS]))
wavTest4 = TestCase(assertEqual "getWaveFile data only" Nothing (getWaveFile $ BS.concat [validWaveHeaderBS, validDataChunkBS]))
wavTest5 = TestCase(assertEqual "getWaveFile header+data" (Just baseWaveFile) (getWaveFile $ BS.concat [validWaveHeaderBS, validFormatChunkBS, validDataChunkBS]))
wavTest6 = TestCase(assertEqual "getWaveFile data+header" Nothing (getWaveFile $ BS.concat [validWaveHeaderBS, validDataChunkBS, validFormatChunkBS]))
wavTest7 = TestCase(assertEqual "getWaveFile header+2data" (Just base2WaveFile) (getWaveFile $ BS.concat [validWaveHeaderBS, validFormatChunkBS, validDataChunkBS, validDataChunkBS]))
wavTest8 = TestCase(assertEqual "getWaveFile header+invalidData" Nothing (getWaveFile $ BS.concat [validWaveHeaderBS, validFormatChunkBS, shortDataChunkBS]))
wavTest9 = TestCase (assertEqual "getWaveFile header+header" Nothing (getWaveFile $ BS.concat [validWaveHeaderBS, validFormatChunkBS, validFormatChunkBS]))
wavTest10 = TestCase (assertEqual "getWaveFile header+data+invalidData" Nothing (getWaveFile $ BS.concat [validWaveHeaderBS, validFormatChunkBS, validDataChunkBS, longDataChunkBS]))

--currently not doing any file validations, so all the incorrect data formations parse (or throw exceptions)
getWaveFileTests =     [TestLabel "getWaveFile null" wavTest1,
                        --TestLabel "getWaveFile invalid" wavTest2,
                        TestLabel "getWaveFile header" wavTest3,
                        --TestLabel "getWaveFile data only" wavTest4,
                        TestLabel "getWaveFile header+data" wavTest5]
                        --TestLabel "getWaveFile data+header" wavTest6,
                        --TestLabel "getWaveFile header+2data" wavTest7] --this fails now because the header length is short
                        --TestLabel "getWaveFile header+invalidData" wavTest8,
                        --TestLabel "getWaveFile header+header" wavTest9, --this doesn't work yet, I think I need to make WaveChunk a class
                    --    TestLabel "getWaveFile header+data+invalidData" wavTest10]
