local PLUGIN = PLUGIN

ENT.Type = "anim"
ENT.Base = "base_entity"
ENT.PrintName = "Smoke Cloud"
ENT.Author = ""
ENT.Information = ""
ENT.Spawnable = false
ENT.AdminSpawnable = false

local smokeimages = { "particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003",
  "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007",
  "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011",
  "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015",
  "particle/smokesprites_0016" }

local function GetSmokeImage()
  return smokeimages[math.random(#smokeimages)]
end

ENT.TacRPSmoke = true
ENT.Particles = nil
ENT.SmokeRadius = 256
ENT.SmokeColor = Color(220, 220, 220)
ENT.BillowTime = 0.5
ENT.Life = 8

AddCSLuaFile()

function ENT:Initialize()
  if SERVER then
    self:SetModel("models/weapons/w_eq_smokegrenade_thrown.mdl")
    self:SetMoveType(MOVETYPE_NONE)
    self:SetSolid(SOLID_NONE)
    self:DrawShadow(false)
  else
    table.insert(PLUGIN.ClientSmokeCache, self)

    local emitter = ParticleEmitter(self:GetPos())

    self.Particles = {}

    local amt = 20

    for i = 1, amt do
      local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
      smoke:SetVelocity(VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 220))
      smoke:SetStartAlpha(0)
      smoke:SetEndAlpha(255)
      smoke:SetStartSize(0)
      smoke:SetEndSize(self.SmokeRadius)
      smoke:SetRoll(math.Rand(-180, 180))
      smoke:SetRollDelta(math.Rand(-0.2, 0.2))
      smoke:SetColor(self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b)
      smoke:SetAirResistance(75)
      smoke:SetPos(self:GetPos())
      smoke:SetCollide(true)
      smoke:SetBounce(0.2)
      smoke:SetLighting(false)
      smoke:SetNextThink(CurTime() + FrameTime())
      smoke.bt = CurTime() + self.BillowTime
      smoke.dt = CurTime() + self.BillowTime + self.Life
      smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(1, 3)
      smoke:SetDieTime(smoke.ft)
      smoke.life = self.Life
      smoke.billowed = false
      smoke.radius = self.SmokeRadius
      smoke:SetThinkFunction(function(pa)
        if not pa then return end

        local prog = 1
        local alph = 0

        if pa.ft < CurTime() then
          -- pass
        elseif pa.dt < CurTime() then
          local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)

          alph = 1 - d
        elseif pa.bt < CurTime() then
          alph = 1
        else
          local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)

          prog = (-d ^ 2) + (2 * d)

          alph = d
        end

        pa:SetEndSize(pa.radius * prog)
        pa:SetStartSize(pa.radius * prog)

        pa:SetStartAlpha(255 * alph)
        pa:SetEndAlpha(255 * alph)

        -- pa:SetLifeTime(pa:GetLifeTime() + FrameTime())
        pa:SetNextThink(CurTime() + FrameTime())
      end)

      table.insert(self.Particles, smoke)
    end

    emitter:Finish()
  end

  self.dt = CurTime() + self.Life + self.BillowTime + 2
end

function ENT:Think()
  if SERVER then
    if not self:GetOwner():IsValid() then
      self:Remove()
      return
    end

    -- local o = self:GetOwner()
    -- local origin = self:GetPos() + Vector(0, 0, 16)

    -- local dmg = DamageInfo()
    -- dmg:SetAttacker(self:GetOwner())
    -- dmg:SetInflictor(self)
    -- dmg:SetDamageType(DMG_NERVEGAS)
    -- dmg:SetDamageForce(Vector(0, 0, 0))
    -- dmg:SetDamagePosition(self:GetPos())
    -- dmg:SetDamageCustom(1024) -- immersive death

    -- util.BlastDamageInfo(dmg, self:GetPos(), 300)

    -- for i, k in pairs(ents.FindInSphere(origin, 300)) do
    --     if k == self:GetOwner() then continue end

    --     if k:IsPlayer() or k:IsNPC() or k:IsNextBot() then
    --         local tr = util.TraceLine({
    --             start = origin,
    --             endpos = k:EyePos() or k:WorldSpaceCenter(),
    --             filter = self,
    --             mask = MASK_SOLID_BRUSHONLY
    --         })
    --         if tr.Fraction < 1 then continue end
    --         local dist = (tr.HitPos - tr.StartPos):Length()
    --         local delta = dist / 320

    --         dmg:SetDamage(k:IsPlayer() and math.Rand(1, 3) or math.Rand(5, 15))

    --         k:TakeDamageInfo(dmg)

    --         if k:IsPlayer() then
    --             k:ScreenFade( SCREENFADE.IN, Color(150, 150, 50, 100), 2 * delta, 0 )

    --             local timername = "tacrp_ninja_gas_" .. k:EntIndex()
    --             local reps = 3

    --             if timer.Exists(timername) then
    --                 reps = math.Clamp(timer.RepsLeft(timername) + 3, reps, 10)
    --                 timer.Remove(timername)
    --             end
    --             timer.Create(timername, 2, reps, function()
    --                 if not IsValid(k) or not k:Alive() then
    --                     timer.Remove(timername)
    --                     return
    --                 end
    --                 k:ScreenFade( SCREENFADE.IN, Color(150, 150, 50, 5), 0.1, 0 )
    --                 if k:Health() > 1 then
    --                     local d = DamageInfo()
    --                     d:SetDamageType(DMG_NERVEGAS)
    --                     d:SetDamage(math.random(1, 2))
    --                     d:SetInflictor(IsValid(self) and self or o)
    --                     d:SetAttacker(o)
    --                     d:SetDamageForce(k:GetForward())
    --                     d:SetDamagePosition(k:GetPos())
    --                     d:SetDamageCustom(1024)
    --                     k:TakeDamageInfo(d)
    --                 else
    --                     k:ViewPunch(Angle(math.Rand(-2, 2), 0, 0))
    --                 end
    --                 if math.random() <= 0.3 then
    --                     k:EmitSound("ambient/voices/cough" .. math.random(1, 4) .. ".wav", 80, math.Rand(95, 105))
    --                 end
    --             end)

    --             if math.random() <= 0.3 then
    --                 k:EmitSound("ambient/voices/cough" .. math.random(1, 4) .. ".wav", 80, math.Rand(95, 105))
    --             end
    --         elseif k:IsNPC() then
    --             k:SetSchedule(SCHED_STANDOFF)
    --         end
    --     end
    -- end

    -- self:NextThink(CurTime() + 1)

    if self.dt < CurTime() then
      SafeRemoveEntity(self)
    end

    return true
  end
end

function ENT:OnRemove()
  if CLIENT then
    timer.Simple(0, function()
      if not IsValid(self) then
        table.RemoveByValue(PLUGIN.ClientSmokeCache, self)
      end
    end)
  end
end

function ENT:Draw()
  return false
end
