module Dodge.Reloading 
    ( crCancelReloading
    , crToggleReloading
    , crHoldReloading
    , stepReloading
    , tryStartLoading
    ) where
import Dodge.Data
import Dodge.Hammer

import Control.Lens
--import Data.Maybe

crCancelReloading :: Creature -> Creature
crCancelReloading cr = cr 
    & crInv . ix (crSel cr) . itConsumption . laProgress %~ const Nothing
    & crInvSel . iselAction .~ NoInvSelAction

stepReloading :: Creature -> Creature
stepReloading cr = case cr ^?! crInvSel . iselAction of
    ReloadAction _ _  (HasHammer HammerUp) -> cr & crInvSel . iselAction .~ NoInvSelAction
    ReloadAction x la _
        | x > 0     -> cr & crInvSel . iselAction . actionProgress -~ 1
            & crInvSel . iselAction . actionHammer . hammerPosition %~ moveHammerUp
        | otherwise -> cr 
            & crInvSel . iselAction . actionHammer . hammerPosition %~ moveHammerUp
            & crInv . ix (crSel cr) . itConsumption %~ doLoadAction la
            & crInv . ix (crSel cr) . itConsumption %~ rotateActionProgress
            & tryNextLoadAction
    _ -> cr

tryNextLoadAction :: Creature -> Creature
tryNextLoadAction cr = case cr ^? crInv . ix (crSel cr) . itConsumption . laProgress . _Just . ix 0 of
    Nothing -> cr & crInvSel . iselAction .~ NoInvSelAction
    Just la -> cr & crInvSel . iselAction . actionProgress .~ _actionTime la
        & crInvSel . iselAction . reloadAction .~ la

crToggleReloading :: Creature -> World -> World
crToggleReloading cr w = case cr ^?! crInvSel . iselAction of
    ReloadAction {} -> w & creatures . ix (_crID cr) . crInvSel . iselAction .~ NoInvSelAction
    _ -> w & creatures . ix (_crID cr) %~ tryStartLoading

crHoldReloading :: Creature -> World -> World
crHoldReloading cr w = w 
    & creatures . ix (_crID cr) . crInvSel . iselAction . actionHammer .~ HasHammer HammerDown

tryStartLoading :: Creature -> Creature
tryStartLoading cr = case ic ^? laProgress . _Just . ix 0 of
    Just la -> cr & startLoadAction la
    Nothing -> case ic ^? laCycle of
        Nothing -> cr
        Just [] -> error ("item has empty load cycle" ++ show (cr ^?! crInv . ix (crSel cr) . itType))
        Just _ | _laLoaded ic >= _laMax ic -> cr
        Just (la:las) -> cr & startLoadAction la
            & crInv . ix (crSel cr) . itConsumption . laProgress ?~ (la:las)
  where
    ic = cr ^?! crInv . ix (crSel cr) . itConsumption

startLoadAction :: LoadAction -> Creature -> Creature
startLoadAction la cr = cr & crInvSel . iselAction .~ ReloadAction (_actionTime la) la NoHammer


rotateActionProgress :: ItemConsumption -> ItemConsumption
rotateActionProgress ic = case ic ^? laProgress . _Just of
    Just (_:la:las) -> ic & laProgress . _Just .~ (la:las)
    _ | _laLoaded ic < _laMax ic -> ic & laProgress ?~ _laCycle ic
    _ -> ic & laProgress .~ Nothing
    

doLoadAction :: LoadAction -> ItemConsumption -> ItemConsumption
doLoadAction la ic = case la of
    LoadEject {}    -> ic & laLoaded .~ 0 & laPrimed .~ False
    LoadInsert {}   -> ic & laLoaded .~ _laMax ic
    LoadAdd   {_insertMax = x}
                    -> ic & laLoaded +~ min x (_laMax ic - _laLoaded ic)
    LoadPrime {}    -> ic & laPrimed .~ True
    
--{- | Start reloading if clip is empty. -}
--crAutoReload :: Creature -> Creature
--crAutoReload cr = case cr ^? ptrItConsumption' . ammoLoaded of
--    Just 0 | _posture (_crStance cr) /= Aiming
--            -> cr & ptrItConsumption . reloadState .~ strictify reloadT
--                  & ptrItConsumption . ammoLoaded  %~ (`fromMaybe` maxA)
--    _      -> cr
--  where 
--    ptrItConsumption = crInv . ix (_crInvSel cr) . itConsumption
--    ptrItConsumption' = crInv . ix (_crInvSel cr) . itConsumption
--    reloadT = cr ^? ptrItConsumption' . reloadTime
--    maxA    = fmap itMaxAmmo $ cr ^? crInv . ix (_crInvSel cr)
