module Reanimate.Morph.Cache
  ( cachePointCorrespondence -- :: Int -> PointCorrespondence -> PointCorrespondence
  ) where

import           Control.Exception
import qualified Data.ByteString        as B
import           Data.Hashable
import           Data.Serialize
import           Reanimate.Cache        (encodeInt)
import           Reanimate.Misc         (renameOrCopyFile)
import           Reanimate.Morph.Common
import           System.Directory
import           System.FilePath
import           System.IO
import           System.IO.Temp
import           System.IO.Unsafe

-- type PointCorrespondence = Polygon → Polygon → (Polygon, Polygon)
cachePointCorrespondence :: Int -> PointCorrespondence -> PointCorrespondence
cachePointCorrespondence ident fn src dst = unsafePerformIO $ do
    root <- getXdgDirectory XdgCache "reanimate"
    createDirectoryIfMissing True root
    let path = root </> template
    hit <- doesFileExist path
    if hit
      then do
        inp <- B.readFile path
        case decode inp of
          Left{} -> do
            removeFile path
            gen path
          Right out -> return out
      else gen path
  where
    gen path = do
      correspondence <- evaluate (fn src dst)
      withSystemTempFile template $ \tmp h -> do
        hClose h
        B.writeFile tmp (encode correspondence)
        renameOrCopyFile tmp path
      return correspondence
    template = encodeInt key <.> "morph"
    key = hashWithSalt ident (src,dst)