module Load where

import Affection as A

import qualified SDL
import Graphics.Rendering.OpenGL.GL.FlushFinish (finish)

import Control.Concurrent (forkIO)
import Control.Concurrent.MVar
import Control.Monad
import Control.Monad.Trans.Resource (ResIO)

import qualified Data.Map as M
import qualified Data.Text as T
import Data.Ecstasy
import Data.Maybe
import qualified Data.Set as S
import Data.String

import System.Exit (exitFailure)

import NanoVG hiding (V2(..))
import NanoVG.Internal.Image

-- internal imports

import Menu.Connect
import Types
import Util

loadLoad :: UserData -> Affection ()
loadLoad ud = do
  ad <- A.get
  wState <- liftIO $ readMVar (worldState ud)
  curWin <- liftIO $ readMVar (window ud)
  tContext <- liftIO $ readMVar (threadContext ud)
  let progress = (0, "Starting up")
  void $ liftIO $ putMVar (stateProgress ud) progress
  _ <- liftIO $ createFont (nano ud) "bedstead"
    (FileName "assets/font/Bedstead-Semicondensed.ttf")
  _ <- liftIO $ forkIO $
    loadFork
      wState
      (fromJust curWin)
      (fromJust tContext)
      (nano ud)
      (stateMVar ud)
      (stateProgress ud)
  SDL.glMakeCurrent (fromJust curWin) (acContext $ head $ glContext ad)
  void $ liftIO $ swapMVar (state ud) Load
  void $ liftIO $ swapMVar (assetFonts ud) (M.fromList
    [ (FontBedstead, "bedstead")
    ]
    )

loadFork
  :: SystemState Entity (AffectionState (AffectionData) ResIO)
  -> SDL.Window
  -> SDL.GLContext
  -> Context
  -> MVar
    ( SystemState Entity (AffectionState (AffectionData) ResIO)
    , StateData
    )
  -> MVar (Float, T.Text)
  -> IO ()
loadFork ws win glc nvg future progress = do
  let stateSteps = 57
      increment = 1 / stateSteps
  SDL.glMakeCurrent win glc
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading icon \"conntroller_blue\""
    )))
  mcontrblue <- createImage nvg (FileName "assets/icons/controller_blue.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading icon \"controller_blue\""
    )))
  mcontrgreen <- createImage nvg (FileName "assets/icons/controller_green.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading icon \"controller_green\""
    )))
  mkbdblue <- createImage nvg (FileName "assets/icons/keyboard_blue.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading icon \"keyboard_blue\""
    )))
  mkbdgreen <- createImage nvg (FileName "assets/icons/keyboard_green.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading icon \"keyboard_green\""
    )))
  marrow <- createImage nvg (FileName "assets/icons/arrow.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_asc\""
    )))
  mwallasc <- createImage nvg (FileName "assets/walls/wall_asc.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_desc\""
    )))
  mwalldesc <- createImage nvg (FileName "assets/walls/wall_desc.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_corner_n\""
    )))
  mwallcornern <- createImage nvg (FileName "assets/walls/wall_corner_n.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_corner_e\""
    )))
  mwallcornere <- createImage nvg (FileName "assets/walls/wall_corner_e.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_corner_s\""
    )))
  mwallcorners <- createImage nvg (FileName "assets/walls/wall_corner_s.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_corner_w\""
    )))
  mwallcornerw <- createImage nvg (FileName "assets/walls/wall_corner_w.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_t_ne\""
    )))
  mwalltne <- createImage nvg (FileName "assets/walls/wall_t_ne.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_t_se\""
    )))
  mwalltse <- createImage nvg (FileName "assets/walls/wall_t_se.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_t_sw\""
    )))
  mwalltsw <- createImage nvg (FileName "assets/walls/wall_t_sw.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_t_nw\""
    )))
  mwalltnw <- createImage nvg (FileName "assets/walls/wall_t_nw.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"wall_cross\""
    )))
  mwallcross <- createImage nvg (FileName "assets/walls/wall_cross.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"box1\""
    )))
  mmiscbox1 <- createImage nvg (FileName "assets/misc/box1.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"tableSW\""
    )))
  mtableSW <- createImage nvg (FileName "assets/table/tableSW.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"tableSE\""
    )))
  mtableSE <- createImage nvg (FileName "assets/table/tableSE.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"tableNE\""
    )))
  mtableNE <- createImage nvg (FileName "assets/table/tableNE.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"tableNW\""
    )))
  mtableNW <- createImage nvg (FileName "assets/table/tableNW.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"tableC1\""
    )))
  mtablec1 <- createImage nvg (FileName "assets/table/tablec1.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"tableC2\""
    )))
  mtablec2 <- createImage nvg (FileName "assets/table/tablec2.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"tableC3\""
    )))
  mtablec3 <- createImage nvg (FileName "assets/table/tablec3.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"tableC4\""
    )))
  mtablec4 <- createImage nvg (FileName "assets/table/tablec4.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"tableCorner\""
    )))
  mtableC <- createImage nvg (FileName "assets/table/tableCorner.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"flipchart\""
    )))
  mmiscFlipchart <- createImage nvg (FileName "assets/misc/flipchart.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"plant1\""
    )))
  mmiscPlant1 <- createImage nvg (FileName "assets/misc/plant1.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"plant2\""
    )))
  mmiscPlant2 <- createImage nvg (FileName "assets/misc/plant2.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"watercooler\""
    )))
  mmiscWatercooler <- createImage nvg (FileName "assets/misc/watercooler.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"vending machine\""
    )))
  mmiscVending <- createImage nvg (FileName "assets/misc/vending.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"Cabinet with Coffee machine SW\""
    )))
  mcabCoffeeSW <- createImage nvg (FileName "assets/cabinet/cabCoffeeSW.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"Cabinet with Coffee machine SE\""
    )))
  mcabCoffeeSE <- createImage nvg (FileName "assets/cabinet/cabCoffeeSE.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"Cabinet with sink SW\""
    )))
  mcabSinkSW <- createImage nvg (FileName "assets/cabinet/cabSinkSW.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"Cabinet with sink SE\""
    )))
  mcabSinkSE <- createImage nvg (FileName "assets/cabinet/cabSinkSE.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"Cabinet with stove SW\""
    )))
  mcabStoveSW <- createImage nvg (FileName "assets/cabinet/cabStoveSW.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"Cabinet with stove SE\""
    )))
  mcabStoveSE <- createImage nvg (FileName "assets/cabinet/cabStoveSE.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"cabinet SW\""
    )))
  mcabinetSW <- createImage nvg (FileName "assets/cabinet/cabinetSW.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"cabinet SE\""
    )))
  mcabinetSE <- createImage nvg (FileName "assets/cabinet/cabinetSE.png") (S.singleton ImagePremultiplied)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading asset \"cabinet corner\""
    )))
  mcabinetCorner <- createImage nvg (FileName "assets/cabinet/cabinetCorner.png") (S.singleton ImagePremultiplied)
  let micons =
        [ mcontrblue, mcontrgreen, mkbdblue, mkbdgreen, marrow
        ]
  when (any isNothing micons) $ do
    liftIO $logIO Error "Failed to load icon assets"
    exitFailure
  let mimgs =
        [ mwallasc, mwalldesc
        , mwallcornern, mwallcornere, mwallcorners, mwallcornerw
        , mwalltne, mwalltse, mwalltsw, mwalltnw, mwallcross
        , mmiscbox1
        , mtableSW, mtableNW, mtableNE, mtableSE, mtableC
        , mtablec1, mtablec2, mtablec3, mtablec4
        , mmiscFlipchart
        , mmiscPlant1, mmiscPlant2
        , mmiscWatercooler, mmiscVending
        , mcabCoffeeSW, mcabCoffeeSE
        , mcabSinkSW, mcabSinkSE
        , mcabStoveSW, mcabStoveSE
        , mcabinetSW, mcabinetSE, mcabinetCorner
        ]
  when (any isNothing mimgs) $ do
    liftIO $logIO Error "Failed to load image assets"
    exitFailure
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"intruder: standing\""
    )))
  -- playerImgs <- loadPlayerSprite "assets/intruder.png" 64 74 nvg
  --   (zipWith (\a b -> (a, [b])) [0..] $ [ImgIntrE .. ImgIntrN] ++ [ImgIntrNE])
  let imgs = zipWith (\a b -> (a, fromJust b))
        [ ImgWallAsc
        .. ImgCabinetCorner
        ]
        mimgs
      icons = zipWith (\a b -> (a, fromJust b))
        [ IconContrBlue
        .. IconArrow
        ]
        micons
      directions = [E .. N] ++ [NE]
      standIds var = map (AnimId var "standing") directions
      walkIds var = map (AnimId var "walking") directions
      standConfigs = map
        (\i -> AnimationConfig (0, i * 74) (64, 74) (64, 0) 1 0 APLoop)
        [0 .. length (standIds AnimIntruder) - 1]
      walkConfigs = map
        (\i -> AnimationConfig (64, i * 74) (64, 74) (64, 0) 6 1.5 APLoop)
        [0 .. length (walkIds AnimIntruder) - 1]
  playerStanding <- loadAnimationSprites "assets/intruder.png" nvg
    (zip (standIds AnimIntruder) standConfigs)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"intruder: walking\""
    )))
  playerWalking <- loadAnimationSprites "assets/intruder.png" nvg
    (zip (walkIds AnimIntruder) walkConfigs)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"jdoem: standing\""
    )))
  jdoemStanding <- loadAnimationSprites "assets/jdoem.png" nvg
    (zip (standIds AnimJDoeM) standConfigs)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"jdoem: walking\""
    )))
  jdoemWalking <- loadAnimationSprites "assets/jdoem.png" nvg
    (zip (walkIds AnimJDoeM) walkConfigs)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"policem: standing\""
    )))
  policemStanding <- loadAnimationSprites "assets/policem.png" nvg
    (zip (standIds AnimPoliceM) standConfigs)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"policem: walking\""
    )))
  policemWalking <- loadAnimationSprites "assets/policem.png" nvg
    (zip (walkIds AnimPoliceM) walkConfigs)
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"copier: stand\""
    )))
  copierStand <- loadAnimationSprites "assets/misc/copier.png" nvg $ zip
    (map (\name -> AnimId AnimCopier name N) ["closed", "open"])
    (map
      (\i -> AnimationConfig (0, i * 74) (64, 74) (0, 0) 1 0 APLoop)
      [0, 1]
    )
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"copier: copy\""
    )))
  copierCopy <- loadAnimationSprites "assets/misc/copier.png" nvg
    [ ( AnimId AnimCopier "copy" N
      , AnimationConfig (64, 0) (64, 74) (64, 0) 4 1 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"cornerComputer: off\""
    )))
  cornerComputerOff <- loadAnimationSprites "assets/misc/tableCornerComputer.png" nvg
    [ ( AnimId AnimComputer "off" N
      , AnimationConfig (0, 0) (64, 74) (64, 0) 2 2 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"cornerComputer: on\""
    )))
  cornerComputerOn <- loadAnimationSprites "assets/misc/tableCornerComputer.png" nvg
    [ ( AnimId AnimComputer "on" N
      , AnimationConfig (128, 0) (64, 74) (0, 0) 1 0 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"cornerComputer: hack\""
    )))
  cornerComputerHack <- loadAnimationSprites "assets/misc/tableCornerComputer.png" nvg
    [ ( AnimId AnimComputer "hack" N
      , AnimationConfig (0, 74) (64, 74) (64, 0) 4 2 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"neComputer: off\""
    )))
  neComputerOff <- loadAnimationSprites "assets/misc/tableSWComputer.png" nvg
    [ ( AnimId AnimComputer "off" NE
      , AnimationConfig (0, 0) (64, 74) (64, 0) 2 2 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"neComputer: on\""
    )))
  neComputerOn <- loadAnimationSprites "assets/misc/tableSWComputer.png" nvg
    [ ( AnimId AnimComputer "on" NE
      , AnimationConfig (128, 0) (64, 74) (0, 0) 1 0 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"neComputer: hack\""
    )))
  neComputerHack <- loadAnimationSprites "assets/misc/tableSWComputer.png" nvg
    [ ( AnimId AnimComputer "hack" NE
      , AnimationConfig (0, 74) (64, 74) (64, 0) 4 2 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"nwComputer: off\""
    )))
  nwComputerOff <- loadAnimationSprites "assets/misc/tableSEComputer.png" nvg
    [ ( AnimId AnimComputer "off" NW
      , AnimationConfig (0, 0) (64, 74) (64, 0) 2 2 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"nwComputer: on\""
    )))
  nwComputerOn <- loadAnimationSprites "assets/misc/tableSEComputer.png" nvg
    [ ( AnimId AnimComputer "on" NW
      , AnimationConfig (128, 0) (64, 74) (0, 0) 1 0 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"nwComputer: hack\""
    )))
  nwComputerHack <- loadAnimationSprites "assets/misc/tableSEComputer.png" nvg
    [ ( AnimId AnimComputer "hack" NW
      , AnimationConfig (0, 74) (64, 74) (64, 0) 4 2 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"toilet: free\""
    )))
  toiletFree <- loadAnimationSprites "assets/misc/toilet.png" nvg
    [ ( AnimId AnimToilet "free" N
      , AnimationConfig (0, 0) (64, 74) (0, 0) 1 0 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"toilet: occupied\""
    )))
  toiletOccupied <- loadAnimationSprites "assets/misc/toilet.png" nvg
    [ ( AnimId AnimToilet "occupied" N
      , AnimationConfig (64, 0) (64, 74) (0, 0) 1 0 APLoop
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"neDoor0: open\""
    )))
  neDoor0open <- loadAnimationSprites "assets/doors/door_desc_0.png" nvg
    [ ( AnimId AnimDoor0 "open" NE
      , AnimationConfig (0, 0) (64, 74) (0, 74) 5 0.25 APOnce
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"neDoor0: shut\""
    )))
  neDoor0shut <- loadAnimationSprites "assets/doors/door_desc_0.png" nvg
    [ ( AnimId AnimDoor0 "shut" NE
      , AnimationConfig (0, 4*74) (64, 74) (0, -74) 5 0.25 APOnce
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"nwDoor0: open\""
    )))
  nwDoor0open <- loadAnimationSprites "assets/doors/door_asc_0.png" nvg
    [ ( AnimId AnimDoor0 "open" NW
      , AnimationConfig (0, 0) (64, 74) (0, 74) 5 0.25 APOnce
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Loading Animation \"nwDoor0: shut\""
    )))
  nwDoor0shut <- loadAnimationSprites "assets/doors/door_asc_0.png" nvg
    [ ( AnimId AnimDoor0 "shut" NW
      , AnimationConfig (0, 4*74) (64, 74) (0, -74) 5 0.25 APOnce
      )
    ]
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "GL_Finish"
    )))
  finish
  modifyMVar_ progress (return . (\(p, _) ->
    ( p + increment
    , "Handing over"
    )))
  putMVar future
    ( ws
    , LoadData
      { loadAssetImages = M.fromList imgs
      , loadAssetAnims  = M.fromList
        ( playerStanding ++
          playerWalking ++
          jdoemStanding ++
          jdoemWalking ++
          policemStanding ++
          policemWalking ++
          copierStand ++
          copierCopy ++
          cornerComputerOff ++
          cornerComputerOn ++
          cornerComputerHack ++
          neComputerOff ++
          neComputerOn ++
          neComputerHack ++
          nwComputerOff ++
          nwComputerOn ++
          nwComputerHack ++
          toiletFree ++
          toiletOccupied ++
          neDoor0shut ++
          neDoor0open ++
          nwDoor0shut ++
          nwDoor0open
        )
      , loadAssetIcons  = M.fromList icons
      }
    )

drawLoad :: UserData -> Affection ()
drawLoad ud = do
  progress <- liftIO $ readMVar (stateProgress ud)
  liftIO $ do
    logIO A.Verbose ("LoadProgress: " <> fromString (show progress))
    drawLoadScreen ud progress

updateLoad :: UserData -> Double -> Affection ()
updateLoad ud _ = do
  mwsld <- liftIO $ tryTakeMVar (stateMVar ud)
  case mwsld of
    Just (_, ld) -> do
      liftIO $ logIO A.Debug "loaded assets, entering menu"
      void $ liftIO $ swapMVar (assetImages ud) (loadAssetImages ld)
      void $ liftIO $ swapMVar (assetAnimations ud) (loadAssetAnims ld)
      void $ liftIO $ swapMVar (assetIcons ud) (loadAssetIcons ld)
      void $ liftIO $ swapMVar (stateData ud) None
      -- loadMap
      loadMenu ud
    Nothing ->
      return ()
