-- Sprites are taken from Sonic 3, code is somewhat adapted/optimized from Ring Racers

-- I wish there was easy way to get number of sprite frames
local NUMFRAMES = 5

local FF_HORIZONTALFLIP = FF_HORIZONTALFLIP or 0

freeslot(
	"SPR_WTRL",
	"SPR_WTRU",

	"S_WATERTRAIL",
	"S_WATERTRAILUNDERLAY",

	"MT_WATERTRAIL",
	"MT_WATERTRAILUNDERLAY"
)

mobjinfo[MT_WATERTRAIL] = {
	spawnstate = S_WATERTRAIL,
	radius = 48*FRACUNIT,
	height = 32*FRACUNIT,
	dispoffset = 1,
	flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP
}

mobjinfo[MT_WATERTRAILUNDERLAY] = {
	spawnstate = S_WATERTRAILUNDERLAY,
	radius = 48*FRACUNIT,
	height = 32*FRACUNIT,
	dispoffset = 1,
	flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP
}

states[S_WATERTRAIL] = {
  sprite = SPR_WTRL,
  frame = A|FF_PAPERSPRITE,
  tics = 2, -- state duration
  action = nil,
  nextstate = S_INVISIBLE
}

states[S_WATERTRAILUNDERLAY] = {
  sprite = SPR_WTRU,
  frame = A|FF_PAPERSPRITE|FF_TRANS50,
  tics = 2, -- state duration
  action = nil,
  nextstate = S_INVISIBLE
}

local function spawnOrMove(x, y, z, type, mo, field)
	local obj = mo[field]

	if not (obj and obj.valid) then
		obj = P_SpawnMobj(x, y, z, type)
		mo[field] = obj
	else
		if obj.state == S_INVISIBLE then
			P_SetOrigin(obj, x, y, z)
		else
			P_MoveOrigin(obj, x, y, z)
		end
	end

	return obj
end

local function MomentumAngle(mo, threshold)
	if FixedHypot(mo.momx, mo.momy) > threshold then
		return R_PointToAngle2(0, 0, mo.momx, mo.momy);
	else
		return mo.angle; // default to facing angle, rather than 0
	end
end

rawset(_G, "P_WaterRunEffect", function(mo, zpos, lscale, rscale)
	assert(mo and mo.valid)

    lscale = lscale or mo.scale
	rscale = rscale or lscale
	
    local sfx = sfx_s3kdbs

    if not S_SoundPlaying(mo, sfx) then
        S_StartSound(mo, sfx)
    end

    -- Near the water plane.
    local forwardangle = R_PointToAngle2(0, 0, mo.momx, mo.momy)
	--local forwardangle = MomentumAngle(mo, 6*mo.scale)
    local moVisualRadius = mo.radius + (8*mo.scale)
    local curFrame = (leveltime % NUMFRAMES)|FF_PAPERSPRITE
    local x1, x2, y1, y2
    local water

    /*x1 = mo.x + mo.momx/2 + P_ReturnThrustX(mo, forwardangle + ANGLE_90, moVisualRadius)
    y1 = mo.y + mo.momy/2 + P_ReturnThrustY(mo, forwardangle + ANGLE_90, moVisualRadius)
    x1 = x1 + P_ReturnThrustX(mo, forwardangle, moVisualRadius) / 24
    y1 = y1 + P_ReturnThrustY(mo, forwardangle, moVisualRadius) / 24

    local angle1 = forwardangle - ANGLE_180 - ANGLE_22h

    x1 = x1 - P_ReturnThrustX(mo, angle1 + ANGLE_180, 48*lscale)
    y1 = y1 - P_ReturnThrustY(mo, angle1 + ANGLE_180, 48*lscale)

    x2 = mo.x + mo.momx/2 + P_ReturnThrustX(mo, forwardangle - ANGLE_90, moVisualRadius)
    y2 = mo.y + mo.momy/2 + P_ReturnThrustY(mo, forwardangle - ANGLE_90, moVisualRadius)
    x2 = x2 + P_ReturnThrustX(mo, forwardangle, moVisualRadius) / 24
    y2 = y2 + P_ReturnThrustY(mo, forwardangle, moVisualRadius) / 24

    local angle2 = forwardangle - ANGLE_180 + ANGLE_22h

    x2 = x2 - P_ReturnThrustX(mo, angle2 + ANGLE_180, 48*rscale)
    y2 = y2 - P_ReturnThrustY(mo, angle2 + ANGLE_180, 48*rscale)*/
	
	x1 = mo.x + mo.momx + P_ReturnThrustX(mo, forwardangle + ANGLE_90, moVisualRadius)
    y1 = mo.y + mo.momy + P_ReturnThrustY(mo, forwardangle + ANGLE_90, moVisualRadius)
    x1 = x1 + P_ReturnThrustX(mo, forwardangle, moVisualRadius) / 24
    y1 = y1 + P_ReturnThrustY(mo, forwardangle, moVisualRadius) / 24

    local angle1 = forwardangle - ANGLE_180 - ANGLE_22h

    x2 = mo.x + mo.momx + P_ReturnThrustX(mo, forwardangle - ANGLE_90, moVisualRadius)
    y2 = mo.y + mo.momy + P_ReturnThrustY(mo, forwardangle - ANGLE_90, moVisualRadius)
    x2 = x2 + P_ReturnThrustX(mo, forwardangle, moVisualRadius) / 24
    y2 = y2 + P_ReturnThrustY(mo, forwardangle, moVisualRadius) / 24

    local angle2 = forwardangle - ANGLE_180 + ANGLE_22h

    -- Left
    -- Underlay
    water = spawnOrMove(x1, y1, zpos, MT_WATERTRAILUNDERLAY, mo, "watertrail_underlay_left")
    water.angle = angle1
    water.destscale = lscale
    water.momx = mo.momx
    water.momy = mo.momy
    water.momz = mo.momz
    P_SetScale(water, lscale)
    water.state = S_WATERTRAILUNDERLAY
    water.frame = curFrame|FF_TRANS50
    water.target = mo

    -- Overlay
    water = spawnOrMove(x1, y1, zpos, MT_WATERTRAIL, mo, "watertrail_overlay_left")
    water.angle = angle1
    water.destscale = lscale
    water.momx = mo.momx
    water.momy = mo.momy
    water.momz = mo.momz
    P_SetScale(water, lscale)
    water.state = S_WATERTRAIL
    water.frame = curFrame
    water.target = mo

    -- Right
    -- Underlay
    water = spawnOrMove(x2, y2, zpos, MT_WATERTRAILUNDERLAY, mo, "watertrail_underlay_right")
    water.angle = angle2
    water.destscale = rscale
    water.momx = mo.momx
    water.momy = mo.momy
    water.momz = mo.momz
    P_SetScale(water, rscale)
    water.state = S_WATERTRAILUNDERLAY
    water.frame = curFrame|FF_TRANS50
    water.target = mo

    -- Overlay
    water = spawnOrMove(x2, y2, zpos, MT_WATERTRAIL, mo, "watertrail_overlay_right")
    water.angle = angle2
    water.destscale = rscale
    water.momx = mo.momx
    water.momy = mo.momy
    water.momz = mo.momz
    P_SetScale(water, rscale)
    water.state = S_WATERTRAIL
    water.frame = curFrame
    water.target = mo
end)
