module Dodge.Item.Weapon.BulletGun.Cane 
    ( bangCane
    , bangCaneX
    , repeater
    , rifle
    , autoRifle
    , burstRifle
    , completeBurstRifle
    , fastBurstRifle
    , miniGunX
    ) where
--import Dodge.Particle.Bullet.HitEffect
import Dodge.Reloading.Action
--import Dodge.WorldEvent.HitEffect
import Dodge.Item.Weapon.BulletGun.Clip
import Dodge.Data
--import Dodge.ChainEffect
import Dodge.Default.Weapon
import Dodge.Default
--import Dodge.Item.Attachment
--import Dodge.Item.Weapon.ExtraEffect
--import Dodge.Item.Weapon.InventoryDisplay
import Dodge.Item.Weapon.AmmoParams
import Dodge.Item.Draw
import Dodge.Item.Weapon.TriggerType
import Dodge.SoundLogic.LoadSound
import Picture
import Geometry
import ShapePicture
import Shape
import Sound.Data
import LensHelp

--import qualified Data.Map.Strict as M
--import qualified Data.Sequence as Seq
--import Control.Lens
--import Control.Monad.State
--import System.Random

bangCane :: Item
bangCane = defaultBulletWeapon
    { _itParams = BulletShooter
        { _muzVel = 0.8
        , _rifling = 0.9
        , _bore = 2
        , _gunBarrels = SingleBarrel 
            { _brlInaccuracy = 0.01
            }
        , _recoil = 50
        , _torqueAfter = 0.1
        , _randomOffset = 0
        }
    , _itUse = ruseAmmoParamsRate 6 upHammer
        [ ammoHammerCheck
        , useTimeCheck
        , withSoundStart tap3S
        , useAmmoAmount 1
        , withTorqueAfter
        , applyInaccuracy
        , withRecoil
        , withSmoke 1 black 20 200 5
        , withMuzFlareI
        ]
    , _itDimension = ItemDimension
        { _dimRad = 8
        , _dimCenter = V3 5 0 0
        , _dimPortage = HeldItem
            {_handlePos =  5
            ,_muzPos    = 15
            }
        , _dimSPic = \it -> noPic $ baseCaneShape
            <> makeSingleClipAt (V3 5 0 3) it
        }
    } & itUse . useAim . aimStance .~ OneHand
    & itType . iyBase .~ BANGCANE
    & itConsumption . laMax .~ 1
    & itConsumption . laCycle .~ [loadPartialInsert 10 1]
bangCaneX :: Int -> Item
bangCaneX i = bangCane
    { _itUse = ruseAmmoParamsRate 6 upHammer
        [ ammoHammerCheck
        , useTimeCheck
        , withSoundItemChoiceStart caneStickSoundChoice
        , useAllAmmo
        , withTorqueAfter
        , duplicateLoadedBarrels
        , applyInaccuracy
        , withMuzFlareI
        , withRecoil
        ]
    , _itDimension = ItemDimension
        { _dimRad = 8
        , _dimCenter = V3 5 0 0
        , _dimPortage = HeldItem
            {_handlePos =  5
            ,_muzPos    = 15
            }
        , _dimSPic = \it -> noPic $ 
            colorSH red (foldMap 
            ((\y ->  upperPrismPoly 3 $ map (+.+ V2 0 y) $ rectXH 15 2)
             . (\k -> fromIntegral k * 5 - ((fromIntegral i - 1) * 2.5))) [0..i-1]
            ) <> caneClipX i it
        }
    } & itUse . useAim . aimWeight .~ 6
      & itUse . useAim . aimRange .~ 1
      & itUse . useAim . aimStance .~ TwoHandFlat
      & itUse . useAim . aimZoom .~ defaultItZoom {_itZoomFac = 1.5}
    & itConsumption . laMax .~ i
    & itParams . gunBarrels .~ MultiBarrel
        {_brlSpread = AlignedBarrels
        ,_brlNum = i
        ,_brlInaccuracy = 0.1
        }
    & itParams . torqueAfter .~ 0.48 + 0.2 * fromIntegral i
    & itType . iyBase .~ BANGCANEX i
caneStickSoundChoice :: Item -> SoundID
caneStickSoundChoice it
    | _laLoaded (_itConsumption it) < 2 = tap3S 
    | otherwise = shotgunS
caneClipX :: Int -> Item -> Shape
caneClipX i it = case  it ^? itConsumption . laLoaded of
    Just la | la > 0 -> foldMap 
            ( (\y -> translateSH (V3 5 0 3) . upperPrismPoly 1 $ map (+.+ V2 0 y) $ square 1.5)
            . (\k -> fromIntegral k * 5 - ((fromIntegral i - 1) * 2.5))) 
            [0..la-1]
    _ -> mempty
rifle :: Item
rifle = bangCane
    { _itDimension = ItemDimension
        { _dimRad = 8
        , _dimCenter = V3 5 0 0
        , _dimPortage = HeldItem
            {_handlePos =  5
            ,_muzPos    = 15
            }
        , _dimSPic = \it -> noPic $ baseRifleShape
            <> makeSingleClipAt (V3 5 0 3) it
        }
    }
    & itUse . useAim . aimStance .~ TwoHandTwist
    & itType . iyBase .~ RIFLE
    & itConsumption . laMax .~ 1
    & itConsumption . laCycle .~ [loadEject 5, loadInsert 5 ,loadPrime 5]
    & itUse . useAim . aimWeight .~ 6
    & itUse . useAim . aimRange .~ 1
--    & itUse . useAim . aimZoom .~ defaultItZoom {_itZoomFac = 1.5}
    & itUse . useAim . aimZoom .~ defaultItZoom {_itZoomFac = 2}
repeater :: Item
repeater = rifle
    & itType . iyModules . at ModRifleMag ?~ EMPTYMODULE
    & itType . iyBase .~ REPEATER
    & itConsumption . laCycle .~ [loadEject 50, loadInsert 40 ,loadPrime 20]
    & itConsumption . laMax .~ 15
    & itDimension . dimSPic .~ (\it -> noPic $ baseRifleShape
            <> makeTinClipAt 0 (V3 10 (-2) 0) it
            )

baseCaneShape :: Shape
baseCaneShape = colorSH red $ upperPrismPoly 3 $ rectXH 15 1.5

baseRifleShape :: Shape
baseRifleShape = colorSH red $ upperPrismPoly 3 $ rectXH 25 2

autoRifle :: Item
autoRifle = repeater
    & itType . iyBase .~ AUTORIFLE
    & itUse . useMods %~ ((ammoCheckI :) . tail)
    & itType . iyModules . at ModAutoMag ?~ EMPTYMODULE
--    & itUse . useDelay . rateMax .~ 6
burstRifle :: Item
burstRifle = repeater
    & itType . iyBase .~ BURSTRIFLE
    & itParams . gunBarrels . brlInaccuracy .~ 0.05
    & itUse . useDelay . rateMax .~ 18
    & itUse . useMods .~
        [ ammoHammerCheck
        , useTimeCheck
        , sideEffectOnFrame 7 (torqueSideEffect 0.2)
        , lockInvFor 7
        , \f it -> repeatOnFrames (take (_laLoaded (_itConsumption it) - 1) [3,6]) f it
        , withSoundStart tap3S
        , useAmmoAmount 1
        , applyInaccuracy
        , withMuzFlareI
        , withRecoil
        ]
fastBurstRifle :: Item
fastBurstRifle = repeater
    & itType . iyBase .~ FASTBURSTRIFLE
    & itParams . gunBarrels . brlInaccuracy .~ 0.06
    & itUse . useDelay . rateMax .~ 18
    & itUse . useMods .~
        [ ammoHammerCheck
        , useTimeCheck
        , sideEffectOnFrame 9 (torqueSideEffect 0.4)
        , lockInvFor 9
        , \f it -> repeatOnFrames (take (_laLoaded (_itConsumption it) - 1) [2,4,6,8]) f it
        , withSoundStart tap3S
        , useAmmoAmount 1
        , applyInaccuracy
        , withMuzFlareI
        , withRecoil
        ]
completeBurstRifle :: Item
completeBurstRifle = repeater
    & itType . iyBase .~ COMPLETEBURSTRIFLE
    & itType . iyModules . at ModRifleMag .~ Nothing
    & itParams . gunBarrels . brlInaccuracy .~ 0.1
    & itUse . useDelay . rateMax .~ 28
    & itUse . useMods .~
        [ ammoHammerCheck
        , useTimeCheck
        , sideEffectOnFrame 15 (torqueSideEffect 0.8)
        , lockInvFor 15
        , \f it -> repeatOnFrames (take (_laLoaded (_itConsumption it) - 1) [1..14]) f it
        , withSoundStart tap3S
        , useAmmoAmount 1
        , applyInaccuracy
        , withMuzFlareI
        , withRecoil
        ]
miniGunUse :: Int -> ItemUse
miniGunUse i = ruseInstant (useAmmoParams $ Just 1) NoHammer $
    [ ammoCheckI
    , withWarmUp crankSlowS
    , withSoundForI mini1S 2
    --, withThinSmokeI
    , withSmoke 1 black 20 200 5
    , withMuzFlareI
    , useAmmoAmount i
    ] <>
    concat [ 
        [ withSidePushI 50
        , torqueBefore 0.05
        , afterRecoil recoilAmount
        , withRandomOffset
        , withOldDir x
        , trigDoAlso (useAmmoParams $ Just x)
        ] | x <- map ((/fromIntegral i) . fromIntegral) [1..i-1]
        ]
    <> 
        [ withSidePushI 50
        , afterRecoil recoilAmount
        , withRandomOffset
        ]
  where
    recoilAmount = 5

miniGunX :: Int -> Item
miniGunX i = defaultAutoGun 
    { _itConsumption = defaultBulletLoadable
        { _laMax = 1500
        , _laLoaded = 1500
        }
        & laCycle .~ [loadEject 40, loadInsert 40 ,loadPrime 40]
    , _itUse = miniGunUse i
        & useDelay .~ WarmUpNoDelay {_warmTime = 0,_warmMax = 100}
        & useAim . aimWeight .~ 6
        & useAim . aimRange .~ 1
        & useAim . aimStance .~ TwoHandTwist
        & useAim . aimZoom .~ defaultItZoom {_itZoomFac = 1.5}
--    , _itFloorPict = miniGunPictItem
    , _itParams = BulletShooter
        { _muzVel = 1
        , _rifling = 0.9
        , _bore = 2
        , _gunBarrels = MultiBarrel 
            {_brlSpread = RotatingBarrels 0.01
            ,_brlNum = i
            ,_brlInaccuracy = 0
            }
        , _recoil = 10
        , _torqueAfter = 0
        , _randomOffset = 10
        }
    , _itEquipPict = pictureWeaponAim (miniGunXPictItem i)
    , _itInvSize = 4
    , _itDimension = ItemDimension
        { _dimRad = 20
        , _dimCenter = V3 5 0 0
        , _dimPortage = HeldItem
            {_handlePos =  5
            ,_muzPos    = 20
            }
        , _dimSPic = miniGunXPictItem i
        }
    }
    & itDimension . dimPortage . muzPos .~ 40
    & itType . iyBase .~ MINIGUNX i
miniGunXPictItem :: Int -> Item -> SPic
miniGunXPictItem i it = miniGunXPict i spin (_laLoaded $ _itConsumption it)
  where
    spin = (-10) * _laLoaded (_itConsumption it) + _warmTime (_useDelay $ _itUse it)

miniGunXPict :: Int -> Int -> Int -> SPic
miniGunXPict i spin _ = 
    (   colorSH red (rotateSHx a barrels)
        <> baseRifleShape
--        <> clip (-1) 0
--        <> clip (-7) 0
    , mempty
    )
  where
    aBarrel = translateSH (V3 15 2 2) baseCaneShape
    barrels = foldMap (\an -> aBarrel & rotateSHx (2*pi * fromIntegral an / fromIntegral i)) [1..i]
    a = fromIntegral spin / 100
    --x = fromIntegral am / 10
--    clip y z = translateSH (V3 0 (-1) z) (rotateSHx (negate $ pi/4) 
--        . upperPrismPoly 2 
--        $ rectNESW (negate $ 3 + 0.25 * x) y 3 (y-5))
