
{-
Support for enough of the AcrossLite .puz format to satisfy X-Word. A mostly
complete description of the format is available here:

  http://www.joshisanerd.com/puz/
-}

module AcrossLite (
    Crossword(..),
    getAcrossLite,
    putAcrossLite) where

import Prelude hiding (getContents)

import Control.Monad
import Data.Binary.Get
import Data.Binary.Put
import qualified Data.ByteString.Lazy as BS

-- TODO: Give this data some proper structure.

data Crossword = Crossword {
    title :: BS.ByteString,
    author :: BS.ByteString,
    copyright :: BS.ByteString,
    width :: Int,
    height :: Int,
    clues :: [BS.ByteString],
    solution :: BS.ByteString,
    grid :: BS.ByteString
    } deriving Show

getAcrossLite = do
    skip 44
    w <- getWord8
    h <- getWord8
    nClues <- fromIntegral `fmap` getWord8
    skip 5
    solution <- getLazyByteString (fromIntegral w * fromIntegral h)
    grid <- getLazyByteString (fromIntegral w * fromIntegral h)
    title <- getLazyByteStringNul
    author <- getLazyByteStringNul
    copyright <- getLazyByteStringNul
    clues <- replicateM nClues getLazyByteStringNul
    notes <- getLazyByteStringNul
    return $ Crossword title author copyright (fromIntegral w) (fromIntegral h)
                 clues solution grid

putNul = putWord8 0

putLazyByteStringNul s = putLazyByteString s >> putNul

putAcrossLite c = do
    replicateM 44 putNul
    putWord8 (fromIntegral $ width c)
    putWord8 (fromIntegral $ height c)
    putWord8 (fromIntegral $ length $ clues c)
    replicateM 5 putNul
    putLazyByteString (solution c)
    putLazyByteString (grid c)
    putLazyByteStringNul (title c)
    putLazyByteStringNul (author c)
    putLazyByteStringNul (copyright c)
    mapM putLazyByteStringNul (clues c)
    putNul

-- main = BS.interact ((\c -> runPut $ putAcrossLite c) . runGet getAcrossLite)

