content: module Cat.Cat
      (idleTextures,
       hurtTextures,
       walkTextures,
       springBootsTextures,
       speedBootsTextures,
       rainBootsTextures,
       ponchoTextures,
       shieldTextures,
       umbrellaTextures,
       skateboardTextures,
       pogostickTextures,
       fallUmbrellaTextures,
       upsUmbrellaTextures,
       laserTextures,
       Cat(Cat),
       initCat,
       catPos,
       catVelocity,
       catDirection,
       catTexture,
       catItemName,
       catItemDuration,
       catAnimations,
       drawCat,
       catHitbox,
       catPoly,
       updateCatVel,
       updateCatPos,
       updateCatAnim,
       updateCatItemDuration) where
  
  import Graphics.Rendering.OpenGL as GL
  import Nxt.Graphics
  import Nxt.Types
  import Settings.CatSettings as CatSettings
  import Settings.Path
  
  data CatAnimations = CatAnimations
      {
          idleTextures            :: [Nxt.Types.Texture],
          hurtTextures            :: [Nxt.Types.Texture],
          walkTextures            :: [Nxt.Types.Texture],
          springBootsTextures     :: [Nxt.Types.Texture],
          speedBootsTextures      :: [Nxt.Types.Texture],
          rainBootsTextures       :: [Nxt.Types.Texture],
          ponchoTextures          :: [Nxt.Types.Texture],
          shieldTextures          :: [Nxt.Types.Texture],
          umbrellaTextures        :: [Nxt.Types.Texture],
          skateboardTextures      :: [Nxt.Types.Texture],
          pogostickTextures       :: [Nxt.Types.Texture],
          fallUmbrellaTextures    :: [Nxt.Types.Texture],
          upsUmbrellaTextures     :: [Nxt.Types.Texture],
          laserTextures           :: [Nxt.Types.Texture]
      }
  
  data Cat = Cat
      {
          catPos          :: Vector2d,
          catVelocity     :: Vector2d,
          catDirection    :: Direction,
          catTexture      :: [Nxt.Types.Texture],
          catItemName     :: String,
          catItemDuration :: Maybe Int,
          catAnimations   :: CatAnimations
      }
  
  -- initCatAnimations
  initCatAnimations :: IO CatAnimations
  initCatAnimations = do
      dataPath        <- getDataDir
      idleTex         <- cycleTextures   (dataPath ++ "/data/cat/cat-idle/cat-idle") 1 CatSettings.catWalkFrameTime
      hurtTex         <- cycleTextures   (dataPath ++ "/data/cat/cat-hurt/cat-hurt") 1 CatSettings.catWalkFrameTime
      walkTex         <- cycleTextures   (dataPath ++ "/data/cat/cat-walk/cat-walk") 10 CatSettings.catWalkFrameTime
      springBootsTex  <- cycleTextures2  (dataPath ++ "/data/cat/cat-springboots/cat-springboots") 3 4 CatSettings.catSpringFrameTime
      speedBootsTex   <- cycleTextures   (dataPath ++ "/data/cat/cat-speedboots/cat-speedboots") 10 CatSettings.catSpeedFrameTime
      rainBootsTex    <- cycleTextures   (dataPath ++ "/data/cat/cat-rainboots/cat-rainboots") 10 CatSettings.catRainFrameTime
      ponchoTex       <- cycleTextures   (dataPath ++ "/data/cat/cat-poncho/cat-poncho") 10 CatSettings.catPonchoFrameTime
      shieldTex       <- cycleTextures   (dataPath ++ "/data/cat/cat-shield/cat-shield") 10 CatSettings.catShieldFrameTime
      umbrellaTex     <- cycleTextures   (dataPath ++ "/data/cat/cat-umbrella/cat-umbrella") 10 CatSettings.catUmbrellaFrameTime
      skateboardTex   <- cycleTextures   (dataPath ++ "/data/cat/cat-skateboard/cat-skateboard") 4 CatSettings.catSkateFrameTime
      pogostickTex    <- cycleTextures2  (dataPath ++ "/data/cat/cat-pogostick/cat-pogostick") 2 3 CatSettings.catPogoFrameTime
      fallUmbrellaTex <- cycleTextures   (dataPath ++ "/data/cat/cat-umbrella/cat-fall-umbrella") 1 CatSettings.catFallUmbrellaFrameTime
      upsUmbrellaTex  <- cycleTextures   (dataPath ++ "/data/cat/cat-upside-down-umbrella/cat-upside-down-umbrella") 1 CatSettings.catFallUmbrellaFrameTime
      laserTex        <- repeatTexturesN (dataPath ++ "/data/cat/cat-laser/cat-laser") 29 30 38 5 41 3
  
      return (CatAnimations idleTex hurtTex walkTex springBootsTex speedBootsTex rainBootsTex
                            ponchoTex shieldTex umbrellaTex skateboardTex pogostickTex
                            fallUmbrellaTex upsUmbrellaTex laserTex)
  
  -- initCat
  initCat :: Vector2d -> IO Cat
  initCat initPos = do
      animations <- initCatAnimations
      let walkTex = walkTextures animations
  
      return (Cat initPos (CatSettings.catWalkVelX, 0.0) DirRight walkTex "" Nothing animations)
  
  -- drawCat
  drawCat :: Cat -> IO ()
  -- the below pattern match is for a very crude hack for the post victory laser screen :(
  drawCat (Cat (540.0, 340.0) _ _ catTex _ _ _) =
      Nxt.Graphics.drawTextureFlip 540.0 340.0 (head catTex) (1.0::GLdouble) False
  drawCat (Cat (catPosX, catPosY) _ catDir catTex _ _ _) =
      Nxt.Graphics.drawTextureFlip (catPosX - (fromIntegral (textureWidth (head catTex)) / 2)) catPosY (head catTex) (1.0::GLdouble) fliped
      where fliped = case catDir of
                      DirLeft -> True
                      DirRight -> False
  
  -- catHitbox
  catHitbox :: Cat -> Nxt.Types.Rect
  catHitbox (Cat (catPosX, catPosY) _ catDir _ _ _ _) =
      Nxt.Types.Rect (catPosX + xOffset - (width / 2)) catPosY  width height
      where width = 50.0
            height = 80.0
            xOffset = case catDir of
                           DirRight -> 25.0
                           DirLeft -> -25.0
  
  -- catPoly
  catPoly :: Cat -> Nxt.Types.Poly
  catPoly (Cat (catPosX, catPosY) _ catDir _ _ _ _) =
      Poly 4 [(catPosX + xOffset - (width / 2), catPosY),
              (catPosX + xOffset + (width / 2), catPosY),
              (catPosX + xOffset + (width / 2), catPosY + height),
              (catPosX + xOffset - (width / 2), catPosY + height)]
      where width = 50.0
            height = 80.0
            xOffset = case catDir of
                           DirRight -> 25.0
                           DirLeft -> -25.0
  
  -- updateCatVel
  updateCatVel :: Cat -> Nxt.Types.Vector2d -> Cat
  updateCatVel c@(Cat (catPosX, catPosY) _ catDir _ _ _ _) (newVelX, newVelY) =
      c {catPos = (catPosX + newVelX, catPosY + newVelY), catVelocity = (newVelX, newVelY),
         catDirection = newDir}
      where newDir
                  | newVelX < 0.0 = DirLeft
                  | newVelX > 0.0 = DirRight
                  | otherwise = catDir
  
  -- updateCatPos
  updateCatPos :: Cat -> Nxt.Types.Vector2d -> Cat
  updateCatPos cat pos =
      cat {catPos = pos}
  
  -- updateCatAnim
  updateCatAnim :: Cat -> Cat
  updateCatAnim cat =
      cat {catTexture = tail (catTexture cat)}
  
  -- updateCatItemDuration
  updateCatItemDuration :: Cat -> Cat
  updateCatItemDuration c@(Cat _ _ _ _ _ Nothing _) = c
  updateCatItemDuration c@(Cat _ _ _ _ _ (Just itemDur) anim) =
      if itemDur <= 0
         then c {catItemDuration = Nothing, catItemName = "NoItem", catTexture = walkTextures anim}
         else c {catItemDuration = Just (itemDur - 1)}
  
  