-- Based on http://hackage.haskell.org/package/thumbnail

module Graphics.Thumbnail
       ( ImageFormat(..)
       , Thumbnail(..)
       , mkThumbnail
       , mkThumbnail'
       , defaultBounds) where

import Prelude
import Graphics.GD
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as L

data ImageFormat = Gif | Jpeg | Png

data Thumbnail = Thumbnail { fmt :: ImageFormat     -- ^ Image Format Type
                           , img :: Image           -- ^ Thumbnail Image
                           , sz  :: Size            -- ^ Thumbnail Size
                           , lbs :: L.ByteString    -- ^ Thumbnail Data
                           , orgImg :: Image        -- ^ Original Image
                           , orgSZ :: Size          -- ^ Original Size
                           , saveFile :: FilePath -> IO ()
                           }

mkThumbnail :: L.ByteString -> IO (Either String Thumbnail)
mkThumbnail = mkThumbnail' defaultBounds

mkThumbnail' :: ((Int,Int),(Int,Int)) -> L.ByteString -> IO (Either String Thumbnail)
mkThumbnail' sizeBounds = thumbnail . L.unpack
  where
    thumbnail ws | length ws >= 3 = thumbnail' ws -- FIXME!
                 | otherwise = return $ Left "unsupported image format"
    
    thumbnail' ws@(0xff:0xd8:_) = thumbnailJpeg ws
    thumbnail' ws@(0x89:0x50:_) = thumbnailPng ws
    thumbnail' ws@(0x47:0x49:0x46:_) = thumbnailGif ws
    thumbnail' _ = return $ Left "unsupported image format"
    
    thumbnailJpeg ws = do
      src <- loadJpegByteString $ BS.pack ws
      size <- imageSize src
      dest <- copyImage src
      let size' = newSize sizeBounds size
      thm <- uncurry resizeImage size' dest
      bs <- saveJpegByteString (-1) thm
      let save fp = saveJpegFile (-1) fp thm
      return $ Right Thumbnail { fmt=Jpeg
                               , img=thm
                               , sz=size'
                               , lbs=strictToLazy bs
                               , orgImg=src
                               , orgSZ=size
                               , saveFile=save
                               }
    
    thumbnailPng ws = do
      src <- loadPngByteString $ BS.pack ws
      size <- imageSize src
      dest <- copyImage src
      let size' = newSize sizeBounds size
      thm <- uncurry resizeImage size' dest
      bs <- savePngByteString thm
      let save fp = savePngFile fp thm
      return $ Right Thumbnail { fmt=Png
                               , img=thm
                               , sz=size'
                               , lbs=strictToLazy bs
                               , orgImg=src
                               , orgSZ=size
                               , saveFile=save
                               }
      
    thumbnailGif ws = do
      src <- loadGifByteString $ BS.pack ws
      size <- imageSize src
      dest <- copyImage src
      let size' = newSize sizeBounds size
      thm <- uncurry resizeImage size' dest
      bs <- saveGifByteString thm
      let save fp = saveGifFile fp thm
      return $ Right Thumbnail { fmt=Gif
                               , img=thm
                               , sz=size'
                               , lbs=strictToLazy bs
                               , orgImg=src
                               , orgSZ=size
                               , saveFile=save
                               }
        
    strictToLazy = L.pack . BS.unpack
    
newSize :: ((Int,Int),(Int,Int)) -> Size -> Size
newSize ((wMin,hMin),(wMax,hMax)) (w, h) | w >= h && wMax*h`div`w > wMin = (wMax, wMax*h`div`w)
               | w >= h && h >= hMin           = (hMin*w`div`h, hMin)
               | w <  h && hMax*w`div`h > hMin = (hMax*w`div`h, hMax)
               | w <  h && w >= wMin           = (wMin, wMin*h`div`w)
               | otherwise = (w, h)

defaultBounds :: ((Int,Int),(Int,Int))
defaultBounds = ((20,20),(60,60))