module Dodge.Item.Weapon.BulletGuns
    ( pistol
    , autoGun
    , multGun
    , miniGun
    , spreadGun
    , ltAutoGun
    , hvAutoGun
    , autogunSpread
    , autoGunPic
    , longGun
    )
    where
import Dodge.Data
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.Bullet
import Dodge.Item.Weapon.TriggerType
import Dodge.SoundLogic.LoadSound
import Picture
import Geometry
import Geometry.Vector3D
import ShapePicture
import Shape

import qualified Data.Sequence as Seq
import Control.Lens

autoGun :: Item
autoGun = defaultAutoGun 
    { _itName = "AUTOGUN"
    , _itIdentity = AutoGun
    , _wpMaxAmmo = 30
    , _wpLoadedAmmo = 30
    , _wpReloadTime = 80
    , _wpReloadState = 0
    , _itUseRate = 5
    , _itUseTime = 0
    , _itUse   = useAmmoParams
    , _itUseModifiers =
        [ ammoCheckI
        , charFiringStratI
            [('S', hammerCheckI)
            ]
        , useTimeCheckI
        , charFiringStratI
            [('M', torqueBefore 0.08) 
            ,('S', torqueBefore 0.05) 
            ]
        , withSoundForI autoBS 5
        --, withSoundForI seagullChatterS 5
        , useAmmo 1
        , withRandomDirI (autogunSpread/2)
        , withMuzFlareI
        , withSmoke 1 black 20 200 5
        ]
    , _wpSpread = autogunSpread
    , _wpRange = 20
    , _itFloorPict = autoGunPic
    , _itAimingSpeed = 0.4
    , _itAimingRange = 1
    , _itZoom = defaultItZoom 
    , _itAimZoom = defaultItZoom {_itZoomFac = 1.5}
    , _itEquipPict = pictureWeaponOnAim
    , _itAttachment = ItCharMode $ Seq.fromList "MS"
    , _itScroll   = scrollCharMode
    , _itInvDisplay = basicWeaponDisplay
    , _wpAmmo = basicBullet    
    }
autoGunPic :: Item -> SPic
autoGunPic it = noPic $
     colorSH red (prismPoly 
        (map (addZ 5) $ rectNESW 2 12 (-2) (-8))
        (map (addZ 0) $ rectNESW 4 12 (-4) (-12))
        )
    <> translateSHf 0 (-1) (rotateSHx (negate $ pi/4) . upperPrismPoly 2 $ rectNESW (negate $ 3 + 0.25 * x) 0 3 (-5))
  where
    x = fromIntegral $ loadedAmmo it

pistol :: Item
pistol = defaultGun 
    { _itName = "PISTOL"
    , _itIdentity = Pistol
    , _wpMaxAmmo = 15
    , _wpLoadedAmmo = 15
    , _wpReloadTime = 40
    , _wpReloadState = 0
    , _itUseRate = 8
    , _itUseTime = 0
    , _itUse = useAmmoParams 
    , _itUseModifiers = 
        [ ammoCheckI
        , hammerCheckI
        , useTimeCheckI
        , withSoundStart tap3S 
        , useAmmo 1
        , randSpreadDir
        , withMuzFlareI
        ]
    , _itLeftClickUse = Nothing
    , _wpSpread = 0.02
    , _wpRange = 20
    , _itFloorPict = pistolPic
    , _itAimingSpeed = 1
    , _itAimingRange = 0
    , _itZoom = defaultItZoom
    , _itEquipPict = pictureWeaponAim pistolPic
    , _itID = Nothing
    , _itInvDisplay = basicWeaponDisplay
    , _itInvColor = white
    , _itTargeting = Nothing
    , _itWorldTrigger = Nothing
    , _wpAmmo = basicBullet
    }
pistolPic :: Item -> SPic
pistolPic it = noPic $ colorSH green (prismPoly 
        (map (addZ 3) $ rectNESW 3 3 (-3) (-3))
        (map (addZ 0) $ rectNESW 5 3 (-5) (-7))
    )
    <> translateSH (V3 (-4) 5.5 4) (rotateSH pi $ bulletClip am)
  where
    am = loadedAmmo it

bulletClip :: Int -> Shape
bulletClip x = rotateSHx (negate $ pi/4) . upperPrismPoly 2 $ rectNESW 3 0 (3 - 0.25 * am) (-5)
  where
    am = fromIntegral x

hvAutoGun :: Item
hvAutoGun = defaultAutoGun 
    { _itName = "AUTO-HV"
    , _itIdentity = HvAutoGun
    , _wpMaxAmmo = 100
    , _wpLoadedAmmo = 100
    , _wpReloadTime = 200
    , _wpReloadState = 0
    , _itUseRate = 25
    , _itUseTime = 0
    , _itUse = useAmmoParams
    , _itUseModifiers =
        [ ammoCheckI
        , rateIncABI 24 7 (torqueBeforeAtLeast 0.1 0.1) (torqueAfterI 0.2)
        , withSoundStart bangEchoS
        , withThinSmokeI
        , withMuzFlareI
        ]
    , _wpRange = 20
    , _itFloorPict = hvAutoGunPic
    , _itAimingSpeed = 0.2
    , _itAimingRange = 1
    , _wpAmmo = hvBullet
    }
hvAutoGunPic :: Item -> SPic
hvAutoGunPic it = 
    ( colorSH orange (prismPoly
        (map (addZ 5) $ rectNESW 3 12 (-3) (-8))
        (map (addZ 0) $ rectNESW 5 12 (-5) (-12))
        )
    <> bulletClip am
    , mempty
    )
  where
    am = loadedAmmo it
ltAutoGun :: Item                           
ltAutoGun = defaultAutoGun 
    { _itName = "AUTO-LT"
    , _itIdentity = LtAutoGun
    , _wpMaxAmmo = 25
    , _wpLoadedAmmo = 25
    , _wpReloadTime = 80
    , _wpReloadState = 0
    , _itUseRate = 3
    , _itUseTime = 0
    , _itUse = useAmmoParams
    , _itUseModifiers = 
        [ ammoCheckI
        , useTimeCheckI
        , withSoundStart tap1S
        , useAmmo 1
        , withRandomDirI 0.1
        , torqueAfterI 0.2
        , withSidePushI 50
        , modClock 2 withMuzFlareI
        ]
    , _wpSpread = 0.5
    , _wpRange = 20
    , _itFloorPict = ltAutoGunPic
    , _itAimingSpeed = 1
    , _itAimingRange = 0
    , _itZoom = defaultItZoom
    , _itAimStance = OneHand
    , _wpAmmo = ltBullet
    }
    & itDimension . muzzleLength .~ 10 
ltAutoGunPic :: Item -> SPic
ltAutoGunPic it = 
    ( colorSH green $ prismPoly 
        (map (addZ 5) $ mirrorXAxis [V2 (-2) 3, V2 5 3, V2 10 0])
        (map (addZ 0) $ mirrorXAxis [V2 (-5) 5, V2 5 5, V2 10 0])
        <> bulletClip am
    , mempty
    )
  where
    am = loadedAmmo it
miniGun :: Item
miniGun = defaultAutoGun 
    { _itName = "MINI-G"
    , _itIdentity = MiniGun
    , _wpMaxAmmo = 1500
    , _wpLoadedAmmo = 1500
    , _wpReloadTime = 200
    , _wpReloadState = 0
    , _wpMaxWarmUp = 100
    , _itUseRate = 0
    , _itUseTime = 0
    , _itUse = useAmmoParamsVelMod vm4
    , _itUseModifiers =
        [ ammoCheckI
        , withWarmUpI crankSlowS
        , useTimeCheckI
        --, afterRecoil recoilAmount
        , withSoundForI mini1S 2
        --, withThinSmokeI
        , torqueAfterI 0.05
        , withSidePushI 53
        , afterRecoil recoilAmount
        , withRandomOffsetI 12
        , trigDoAlso (useAmmoParamsVelMod vm1)
        --, torqueBeforeForcedI 0.001
        , withSidePushI 52
        , afterRecoil recoilAmount
        , withRandomOffsetI 11
        , withOldDir od1
        , trigDoAlso (useAmmoParamsVelMod vm2)
        --, torqueBeforeForcedI 0.001
        , withSidePushI 51
        , afterRecoil recoilAmount
        , withRandomOffsetI 10
        , withOldDir od2
        , trigDoAlso (useAmmoParamsVelMod vm3)
        , useAmmo 4
        --, torqueBeforeForcedI 0.001
        , withSidePushI 50
        , afterRecoil recoilAmount
        , withRandomOffsetI 9
        , withMuzFlareI
        , withOldDir od3
        , withSmoke 1 black 20 200 5
        ]
    , _wpRange = 20
    , _itFloorPict = miniGunPictItem
    , _itAimingSpeed = 0.4
    , _itAimingRange = 1
    , _itEquipPict = pictureWeaponAim miniGunPictItem
    , _wpAmmo = basicBullet
    } & itDimension . muzzleLength .~ 15
  where
    recoilAmount = 5
    [vm1,vm2,vm3,vm4] = 
        [ 0.25
        , 0.5
        , 0.75
        , 1
        ]
    [od1,od2,od3] = 
        [ 0.25, 0.5, 0.9]
        --[ 0.75, 0.5, 0.25]
        --[ 0, 0, 0]
miniGunPictItem :: Item -> SPic
miniGunPictItem it = miniGunPict spin (loadedAmmo it)
  where
    spin = (-10) * _wpLoadedAmmo it + _wpCurWarmUp it

miniGunPict :: Int -> Int -> SPic
miniGunPict spin am = 
    (   colorSH red (rotateSHx a barrels)
        <> colorSH red (upperPrismPoly 5 $ rectNESW 8 8 (-8) 4)
        <> colorSH red (prismPoly 
                (map (addZ 5) $ rectNESW 2 12 (-2) (-12))
                (map (addZ 0) $ rectNESW 4 12 (-4) (-16))
            )
        <> clip (-1) 0
        <> clip (-7) 0
    , mempty
    )
  where
    aBarrel = translateSH (V3 7 0 9) $ prismPoly
        (map (addZ 5) $ rectNESW 2 12 (-2) (-1))
        (map (addZ 0) $ rectNESW 4 12 (-4) (-5))
    barrels = concatMap (\an -> aBarrel & rotateSHx an) [0,0.5* pi, pi, 1.5*pi]
    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))
spreadGun :: Item
spreadGun = defaultGun 
    { _itName = "SPREAD"
    , _itIdentity = SpreadGun
    , _wpMaxAmmo = 5
    , _wpLoadedAmmo = 5
    , _wpReloadTime = 80
    , _wpReloadState = 0
    , _itUseRate = 20
    , _itUseTime = 0
    --, _itUse = \_ -> spreadNumVelWthHiteff spreadGunSpread 9 (V2 30 0) 2 basicBulletEffect
    , _itUse = useAmmoParams
    , _itUseModifiers =
        [ ammoCheckI
        , hammerCheckI
        , useTimeCheckI
        , withSoundStart shotgunS
        , useAmmo 1
        , withRecoilI 100
        , withMuzFlareI
        , spreadNumI
        ]
    , _wpSpread = spreadGunSpread
    , _wpRange = 20
    , _itFloorPict = spreadGunPic
    , _itAimingSpeed = 1
    , _itAimingRange = 0
    , _wpAmmo = basicBullet
    , _wpNumBarrels = 50
    }
spreadGunPic :: Item -> SPic
spreadGunPic it = 
    ( colorSH green (upperPrismPoly 5 $ map toV2[(-3,0),(3,6),(3,-6)])
    <> bulletClip am
    , mempty
    )
  where
    am = loadedAmmo it
multGun :: Item
multGun = defaultGun 
    { _itName = "MULTGUN"
    , _itIdentity = MultGun
    , _wpMaxAmmo = 2
    , _wpLoadedAmmo = 2
    , _wpReloadTime = 40
    , _wpReloadState = 0
    , _itUseRate = 20
    , _itUseTime = 0
    , _itUse = useAmmoParams
    , _itUseModifiers =
        [ ammoCheckI
        , hammerCheckI
        , useTimeCheckI
        , withSoundStart shotgunS
        , useAmmo 1
        , withRecoilI 200
        , withMuzFlareI
        , numI
        ]
    , _wpSpread = spreadGunSpread
    , _wpRange = 20
    , _itFloorPict = multGunSPic
    , _itAimingSpeed = 0.4
    , _itAimingRange = 1
    , _itZoom       = defaultItZoom
    , _itAimZoom    = defaultItZoom {_itZoomFac = 1.5}
    , _itAimStance = TwoHandTwist
    , _wpAmmo = basicBullet
    , _wpNumBarrels = 5
    }
multGunSPic :: Item -> SPic
multGunSPic it = 
    ( colorSH red (
        upperPrismPoly 2 (rectNESW 4 8 (-4) (-12)) <>
        translateSHf 8 0 (concatMap barrel [12,7,2,-3,-8] <> 
            upperPrismPoly 2 (map toV2 [(-1.5,12),(-2,12),(-2,-12),(-1.5,-12)])
            )
    ) <> bulletClip am
    , mempty
    )
  where
    barrel y = prismPoly 
        (map (addZ 5) $ rectNSEW y (y-4) 2   0 )
        (map (addZ 0) $ rectNSEW y (y-4) 2 (-2))
    am = loadedAmmo it
longGun :: Item
longGun = defaultGun 
    { _itName = "LONGGUN"
    , _itIdentity = LongGun
    , _wpMaxAmmo = 1
    , _wpLoadedAmmo = 1
    , _wpReloadTime = 100
    , _wpReloadState = 0
    , _wpReloadType = PassiveReload skwareFadeTwoSecS
    , _itUseRate = 100
    , _itUseTime = 0
    , _itUse = useAmmoParams
    , _itUseModifiers =
        [ ammoCheckI
        , hammerCheckI
        , useTimeCheckI
        , withSoundStart bangEchoS
        , useAmmo 1
        , withThickSmokeI
        , torqueAfterI 0.05
        , withMuzFlareI
        ]
    , _wpRange = 200
    , _itFloorPict = longGunSPic
    , _itAimingSpeed = 0.2
    , _itAimingRange = 1
    , _itZoom       = defaultItZoom 
    , _itAimZoom    = defaultItZoom {_itZoomMax = 0.5, _itZoomMin = 0.5}
    , _itScroll = zoomLongGun
    , _itAttachment = ItScope (V2 0 0) 0 1 False
    , _itEffect = itemLaserScopeEffect
    , _wpAmmo = hvBullet
    , _itAimStance = TwoHandTwist
    }
longGunSPic :: Item -> SPic
longGunSPic _ =
    ( colorSH orange $ upperPrismPoly 5 $ rectWH 12 2
    , mempty
    )

zoomLongGun :: Float -> Creature -> Item -> Item
zoomLongGun x _
    | x > 0 = startZoomInLongGun 
    | x < 0 = startZoomOutLongGun
    | otherwise = id

startZoomInLongGun :: Item -> Item
startZoomInLongGun   = itAttachment . scopeZoomChange %~ \x -> max 5 (x + 5)
startZoomOutLongGun :: Item -> Item
startZoomOutLongGun  = itAttachment . scopeZoomChange %~ \x -> min (-5) (x-5)

spreadGunSpread :: Float
spreadGunSpread = 0.5
autogunSpread :: Float
autogunSpread = 0.07
