content: 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,getReanimateCacheDirectory)
  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 <- getReanimateCacheDirectory
      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)
  