local mod = get_mod("ShenheFriendly")
-- Your mod code goes here.
-- https://vmf-docs.verminti.de
--[[
 /scripts/utilities/attack/impact_effect.lua
 \scripts\extension_systems\fx\fx_system.lua
 \scripts\settings\impact_fx\impact_fx_sawing_2h.lua
 SharedGibbingTemplates = require("scripts/managers/minion/minion_gibbing_templates/shared_gibbing_templates")
 blood_fountain = {
	particle_effect = "content/fx/particles/impacts/flesh/blood_gushing_01"
}
 blood_fountain = {
	node_name = "fx_blood",
	particle_effect = "content/fx/particles/impacts/flesh/blood_fountain_head_01"
}
SharedGibbingTemplates.vfx.blood_splatter = {
	particle_effect = "content/fx/particles/impacts/flesh/blood_splatter_gib_torso_small_01",
	linked = false
}
--]]
local BuffTemplates = require("scripts/settings/buff/buff_templates")
local user_see_no_evil = {}
local function shenhe_happiness_sekai_filter()
	local filter = type(mod:get("shenhe_id_filtered")) == "number" and mod:get("shenhe_id_filtered") or 1
	return mod:localize(string.format("shenhe_filter_%s",filter))
end
mod.shenhe_unhappy_names = {}
mod.shenhe_id = {others = mod:get("shenhe_others"),me = mod:get("shenhe_myself")}
mod.shenhe_id_filtered = shenhe_happiness_sekai_filter()
local function bleed_like_effect(path,material_emission,orphaned_policy,stop_type,node_name)
	local effect = {
				{
					node_name = node_name or "j_spine",
					vfx = {
						material_emission = material_emission,
						particle_effect = path,
						orphaned_policy = orphaned_policy or "destroy",
						stop_type = stop_type or "stop"
					}
				},
			}
	return effect
end

mod.chain_effects = {
	spark = "content/fx/particles/impacts/weapons/chainsword/chainsword_grinding_sparks_loop_01",
	force = "content/fx/particles/impacts/weapons/force_sword/force_sword_stuck_looping",
}

mod.buff_effects = {
	bleed = bleed_like_effect("content/fx/particles/enemies/buff_bleeding",true),
	chainlightning = bleed_like_effect("content/fx/particles/enemies/buff_chainlightning",true),
	nurgle_blessing = bleed_like_effect("content/fx/particles/enemies/buff_nurgle_blessing"),
	force = bleed_like_effect("content/fx/particles/impacts/weapons/force_sword/force_sword_stuck_looping"),
	fire = bleed_like_effect("content/fx/particles/enemies/buff_burning",true),
	warp_fire = bleed_like_effect("content/fx/particles/enemies/buff_warpfire",true),
	green_fire = bleed_like_effect("content/fx/particles/enemies/buff_burning_green",true),
	--lighting_1 = "content/fx/particles/abilities/protectorate_chainlightning_charging_hands",
	--smite = "content/fx/particles/abilities/psyker_smite_chargeup_hands_01",
	--flame_staff = "content/fx/particles/weapons/flame_staff/psyker_flame_staff_charge",
	red_eyes = {
		{
			node_name = "j_righteye",
			vfx = {
				orphaned_policy = "stop",
				particle_effect = "content/fx/particles/enemies/red_glowing_eyes",
				stop_type = "destroy",
			},
		},
		{
			node_name = "j_lefteye",
			vfx = {
				orphaned_policy = "stop",
				particle_effect = "content/fx/particles/enemies/red_glowing_eyes",
				stop_type = "destroy",
			},
		},
	},
}
mod.vfx_units = {}
mod.shenhe_gib = {
	warp = {
		["content/fx/particles/impacts/flesh/blood_fountain_head_01"] = "content/fx/particles/impacts/flesh/gib_splatter_force_01",
		["content/fx/particles/impacts/flesh/blood_gushing_01"] = "content/fx/particles/impacts/flesh/gib_splatter_force_01",
		["content/fx/particles/impacts/flesh/blood_splatter_gib_torso_small_01"] = "content/fx/particles/impacts/flesh/gib_splatter_force_01",
		-- poxwalker
		["content/fx/particles/impacts/flesh/poxwalker_blood_fountain_head_01"] = "content/fx/particles/impacts/flesh/gib_splatter_force_01",
		["content/fx/particles/impacts/flesh/poxwalker_blood_gushing_01"] = "content/fx/particles/impacts/flesh/gib_splatter_force_01",
		["content/fx/particles/impacts/flesh/poxwalker_splatter_gib_torso_small_01"] = "content/fx/particles/impacts/flesh/gib_splatter_force_01",
	},
	bloodless = {
		["content/fx/particles/impacts/flesh/blood_fountain_head_01"] = "content/fx/particles/enemies/buff_chainlightning",
		["content/fx/particles/impacts/flesh/blood_gushing_01"] = "content/fx/particles/enemies/buff_chainlightning",
		["content/fx/particles/impacts/flesh/blood_splatter_gib_torso_small_01"] = "content/fx/particles/enemies/buff_chainlightning",
		-- poxwalker
		["content/fx/particles/impacts/flesh/poxwalker_blood_fountain_head_01"] = "content/fx/particles/enemies/buff_chainlightning",
		["content/fx/particles/impacts/flesh/poxwalker_blood_gushing_01"] = "content/fx/particles/enemies/buff_chainlightning",
		["content/fx/particles/impacts/flesh/poxwalker_splatter_gib_torso_small_01"] = "content/fx/particles/enemies/buff_chainlightning",
	},
}

local GibbingSettings = require("scripts/settings/gibbing/gibbing_settings")
local GibbingTypes = GibbingSettings.gibbing_types
local function replace_stump_vfx(stump_settings)
	if stump_settings and stump_settings.vfx and stump_settings.vfx.particle_effect and mod.shenhe_gib[mod.shenhe_impact_gib] and mod.shenhe_gib[mod.shenhe_impact_gib][stump_settings.vfx.particle_effect] then
		stump_settings.vfx.particle_effect = mod.shenhe_gib[mod.shenhe_impact_gib][stump_settings.vfx.particle_effect]
	end
end

mod:hook("MinionGibbing","spawn_gib_from_queue",function(func,self, unit, gib_settings, gib_position, gib_rotation, hit_zone_name, attack_direction, damage_profile, hit_zone_gib_template, optional_override_gib_forces)
	if mod.shenhe_impact_gib ~= "disable" then
		local vfx = gib_settings.vfx
		local shenhe_sub = mod.shenhe_impact_gib
		if mod.shenhe_impact_gib == "simple_warp" then
			shenhe_sub = "warp"
		end
		if vfx and vfx.particle_effect and mod.shenhe_gib[shenhe_sub] and mod.shenhe_gib[shenhe_sub][vfx.particle_effect] then
			vfx.particle_effect = mod.shenhe_gib[shenhe_sub][vfx.particle_effect]
		end
	end
	func(self, unit, gib_settings, gib_position, gib_rotation, hit_zone_name, attack_direction, damage_profile, hit_zone_gib_template, optional_override_gib_forces)
end)

-- _get_gibbing_template(self._template, gibs, hit_zone_name_or_nil, gibbing_type, self._portable_random, debug_explicit_gib_index)
-- _get_gibbing_template(gib_template, gibs, hit_zone_name, gibbing_type, portable_random, debug_explicit_gib_index)
-- local hit_zone_gib_template = gib_template[hit_zone_name] and (gib_template[hit_zone_name][gibbing_type] or gib_template[hit_zone_name].default) or gib_template.fallback_hit_zone and (gib_template.fallback_hit_zone[gibbing_type] or gib_template.fallback_hit_zone.default)
mod:hook("MinionGibbing","gib",function(func,self, hit_zone_name_or_nil, attack_direction, damage_profile, override_gib_type, optional_override_gib_forces, optional_is_critical_strike)
	if mod.shenhe_impact_gib == "simple_warp" then
		override_gib_type = "warp"
	elseif mod.shenhe_impact_gib == "warp" or mod.shenhe_impact_gib == "bloodless" then
		local template_full_list = self._template
		local gibbing_type = override_gib_type or damage_profile.gibbing_type or GibbingTypes.default
		
		if optional_is_critical_strike then
			local critical_strike_settings = damage_profile.critical_strike
			if critical_strike_settings then
				gibbing_type = critical_strike_settings.gibbing_type or gibbing_type
			end
		end
		
		local hit_zone_gib_template = template_full_list[hit_zone_name_or_nil] and (template_full_list[hit_zone_name_or_nil][gibbing_type] or template_full_list[hit_zone_name_or_nil].default) or template_full_list.fallback_hit_zone and (template_full_list.fallback_hit_zone[gibbing_type] or template_full_list.fallback_hit_zone.default)
		
		if hit_zone_gib_template then
			local gibs = self._gibs
			local conditional_gibbing = hit_zone_gib_template.conditional
			if conditional_gibbing then
				for i = 1,#conditional_gibbing do
					local template = conditional_gibbing[i]
					local condition = template.condition
					local already_gibbed_condition = condition.already_gibbed
					local conditional_template = nil
					
					if already_gibbed_condition then
						if gibs[already_gibbed_condition] ~= nil then
							conditional_template = template
						end
					elseif condition.always_true then
						conditional_template = template
					end
					
					if conditional_template then
						replace_stump_vfx(conditional_template.stump_settings)
						break
					end
				end
			else
				local num_entries = #hit_zone_gib_template
				if num_entries > 0 then
					for i = 1, num_entries do
						replace_stump_vfx(hit_zone_gib_template[i].stump_settings)
					end
				else
					replace_stump_vfx(hit_zone_gib_template.stump_settings)
				end
			end
		end
	--elseif mod.shenhe_impact_gib == "disable" then
	end
	return func(self, hit_zone_name_or_nil, attack_direction, damage_profile, override_gib_type, optional_override_gib_forces, optional_is_critical_strike)
end)
-- on hit
mod:hook('FxSystem','play_impact_fx',function(func,self, impact_fx, position, direction, source_parameters, attacking_unit, optional_target_unit, optional_node_index, optional_hit_normal, optional_will_be_predicted, local_only_or_nil)
	if mod.shenhe_impact and impact_fx.vfx and not table.is_empty(impact_fx.vfx) then
		local shenhe = impact_fx.vfx
		for i = 1, #shenhe do
			if shenhe[i].effects and shenhe[i].effects[1] then
				if string.find(shenhe[i].effects[1],"blood_splatter_reduced_damage") then
					shenhe[i].effects[1] = "content/fx/particles/impacts/armor_penetrate"
				elseif string.find(shenhe[i].effects[1],"blood") then
					shenhe[i].effects[1] = "content/fx/particles/impacts/generic_dust_unarmored"
				end
			end
		end
	end
	func(self, impact_fx, position, direction, source_parameters, attacking_unit, optional_target_unit, optional_node_index, optional_hit_normal, optional_will_be_predicted, local_only_or_nil)
end)

mod.bring_shenhe_happiness_sekai_bleed_effect = function(func,self,index,template)
	local node_effects = template.minion_effects and template.minion_effects.node_effects
	local template_isekai = template
	local shenhe_unhappy = node_effects and template.name == "bleed"
	if shenhe_unhappy then
		local buff_context = self._buff_context
		local name = buff_context and buff_context.breed and buff_context.breed.name
		if not mod.vfx_units[self._unit] then
			mod.vfx_units[self._unit] = self._vfx_node_effects
		end
		if mod.setting_bleed_effect == "red_eyes" and name and table.array_contains({"cultist_mutant","chaos_spawn"},name) then
			template_isekai = mod.shenhe_happiness_sekai_bleed_effect.eyeless
		else
			template_isekai = mod.shenhe_happiness_sekai_bleed_effect.default
		end
	end
	func(self,index,template_isekai)
end

-- debuff \scripts\extension_systems\buff
mod:hook("MinionBuffExtension","_start_fx" ,mod.bring_shenhe_happiness_sekai_bleed_effect)
mod:hook("MinionBuffExtension","_stop_fx" ,mod.bring_shenhe_happiness_sekai_bleed_effect)

-- Chainsaw effects
local player_character_particles = require("scripts/settings/particles/player_character_particles")
local particle_aliases = require("scripts/settings/particles/player_character_particle_aliases")
mod:hook(player_character_particles,"resolve_particle",function (func,particle_alias, properties, optional_external_properties)
	if particle_alias == "melee_sticky_loop" and mod.setting_chain_effect ~= "default" then
		local settings = particle_aliases[particle_alias]
		if settings then
			local particles = settings.particles
			local switches = settings.switch
			local no_default = settings.no_default
			local num_switches = #switches
			local DEFAULT_EXTERNAL_PROPERTIES = {}
			
			if num_switches ~= 0 then
				for i = 1, num_switches do
					local switch_name = switches[i]
					local switch_property = properties[switch_name] or (optional_external_properties or DEFAULT_EXTERNAL_PROPERTIES)[switch_name]

					if switch_property and particles[switch_property] then
						particles = particles[switch_property]
					elseif not no_default then
						particles = particles.default
					end

					if type(particles) == "string" then
						if string.find(particles,"blood") then
							particles = mod.chain_effects[mod.setting_chain_effect]
						end
						return true, particles
					end
				end
			end
		end
	end	
	return func(particle_alias, properties, optional_external_properties)
end)

local function bleed_eyes()
	if mod.setting_bleed_effect == "red_eyes" then
		local eye_colors = {
			blue = {0,0.75,0.75},
			green = {0,	0.75,0.005},
			red = {0.9,0,0.005},
			yellow = {0.358,0.786,0.22},
			purple = {0.75,0,0.75},
		}
		local intensity = mod:get("setting_bleed_effect_eye_color_intensity") or 0.05
		mod.shenhe_happiness_sekai_bleed_effect.default.minion_effects.material_vector = {
			name = "stimmed_color",
			value = {
				mod:get("setting_bleed_effect_eye_stimmed_color_R"),
				mod:get("setting_bleed_effect_eye_stimmed_color_G"),
				mod:get("setting_bleed_effect_eye_stimmed_color_B"),
			}
		}
		for i = 1,2 do
			local color = eye_colors[mod:get("setting_bleed_effect_eye_color_"..tostring(i))] or {
				mod:get("setting_bleed_effect_eye_color_"..tostring(i).."_R"),
				mod:get("setting_bleed_effect_eye_color_"..tostring(i).."_G"),
				mod:get("setting_bleed_effect_eye_color_"..tostring(i).."_B"),
			}
			mod.shenhe_happiness_sekai_bleed_effect.default.minion_effects.node_effects[i].vfx.material_variables = {
				{
					variable_name = "material_variable_21872256",
					material_name = "eye_flash_init",
					value = {color[1]*intensity,color[2]*intensity,color[3]*intensity,}
				},
				{
					variable_name = "material_variable_21872256",
					material_name = "eye_socket",
					value = color
				},
				{
					variable_name = "trail_color",
					material_name = "eye_glow",
					value = color
				},
				{
					variable_name = "material_variable_21872256_69bf7e2a",
					material_name = "eye_glow",
					value = color
				},
			}
		end
	end
end

local function on_bleed_effect_change(which_one)
	local old = mod[which_one]
	local path = mod.buff_effects[old][1].vfx.particle_effect
	local refuse = false
	local dum = false
	for unit,vfx in pairs(mod.vfx_units) do
		if vfx and not table.is_empty(vfx) then
			for k,node in pairs(vfx) do
				if node[path] then
					refuse = true
					break
				end
			end
			if refuse then break end
		else
			mod.vfx_units[unit] = nil
		end
	end
	if refuse then
		mod:notify(mod:localize("plz_change_later"))
		mod:set(which_one,old)
	else
		mod[which_one] = mod:get(which_one)
		local sekai = {
			setting_bleed_effect = "default",
			setting_bleed_effect_eyeless = "eyeless"
		}
		mod.shenhe_happiness_sekai_bleed_effect[sekai[which_one]].minion_effects.node_effects = mod.buff_effects[mod[which_one]]
		bleed_eyes()
	end
end
--[[
<bleed>
[class_name] = interval_buff (string)
[duration] = 1.5 (number)
[max_stacks] = 16 (number)
[icon] = content/ui/materials/icons/abilities/default (string)
[keywords] = table
  [1] = bleeding (string)
[interval_func] = [function]
[minion_effects] = table
  [node_effects] = table
    [1] = table
      [vfx] = table
        [stop_type] = stop (string)
        [orphaned_policy] = destroy (string)
        [particle_effect] = content/fx/particles/enemies/buff_bleeding (string)
        [material_emission] = true (boolean)
      [node_name] = j_spine (string)
[max_stacks_cap] = 16 (number)
[refresh_duration_on_stack] = true (boolean)
[predicted] = false (boolean)
[interval_stack_removal] = true (boolean)
[buff_category] = generic (string)
[name] = bleed (string)
[interval] = 0.5 (number)
</bleed>
--]]
mod.ready_shenhe_happiness_sekai_bleed_effect = function()
	if not mod.shenhe_happiness_sekai_bleed_effect then
		local bleed_effect = BuffTemplates.bleed
		mod.shenhe_happiness_sekai_bleed_effect = {
			default = table.clone(bleed_effect),
			eyeless = table.clone(bleed_effect),
		}
	end
	mod.shenhe_happiness_sekai_bleed_effect.default.minion_effects.node_effects = mod.buff_effects[mod.setting_bleed_effect]
	mod.shenhe_happiness_sekai_bleed_effect.eyeless.minion_effects.node_effects = mod.buff_effects[mod.setting_bleed_effect_eyeless]
	bleed_eyes()
end

mod.init = function(self)
	mod.setting_chain_effect = mod:get("setting_chain_effect")
	mod.setting_bleed_effect = mod:get("setting_bleed_effect")
	mod.setting_bleed_effect_eyeless = mod:get("setting_bleed_effect_eyeless")
	mod.shenhe_impact = mod:get("shenhe_impact")
	mod.shenhe_impact_gib = mod:get("shenhe_impact_gib")
	mod.ready_shenhe_happiness_sekai_bleed_effect()
	mod.ShenheSeeNoEvil = mod:io_dofile("ShenheFriendly/scripts/mods/ShenheFriendly/ShenheSeeNoEvil")
	user_see_no_evil =  mod:get("shenhe_unhappy_words") or {}
	table.append(mod.ShenheSeeNoEvil,user_see_no_evil)
	mod.shenhe_unhappy_names = {}
	mod.shenhe_id_filtered =  shenhe_happiness_sekai_filter()
	mod.shenhe_id = {others = mod:get("shenhe_others"),me = mod:get("shenhe_myself"),myid = mod:get("shenhe_myself_myid")}
end
mod.on_setting_changed = function(setting_name)
	if (setting_name == "setting_bleed_effect" and mod.setting_bleed_effect ~= mod:get("setting_bleed_effect")) or (setting_name == "setting_bleed_effect_eyeless" and mod.setting_bleed_effect_eyeless ~= mod:get("setting_bleed_effect_eyeless")) then
		on_bleed_effect_change(setting_name)
	else
		mod:init()
	end
end
mod.on_all_mods_loaded = function()
	mod:init()
end
mod.on_game_state_changed = function(status, state_name)
	if status == "exit" and not table.is_empty(mod.vfx_units) then
		mod.vfx_units = {}
	end
end

mod:command("shenheid",mod:localize("shenhe_id_command"),function(order,...)
	local all_key_words = table.concat(mod.ShenheSeeNoEvil,"，")
	if not order then
		local streaming = mod:get("shenhe_streaming")
		all_key_words = streaming and mod:localize("shenhe_is_streaming") or all_key_words
		mod:echo(mod:localize("echo_all_evil_words",all_key_words))		
	else
		local words = {...}
		if order == "myid" then
			mod.shenhe_id.myid = #words > 0 and table.concat(words," ") or nil
			mod:set("shenhe_myself_myid",mod.shenhe_id.myid)
		elseif #words > 0 then
			for k,key_word in pairs(words) do
				if order == "add" then
					if not string.find(all_key_words,key_word) then
						user_see_no_evil[#user_see_no_evil + 1] = key_word
						mod.ShenheSeeNoEvil[#mod.ShenheSeeNoEvil + 1] = key_word
						all_key_words = all_key_words.."，"..key_word
						mod:notify(mod:localize("shenhe_add_key_word",key_word))
					end
				elseif order == "dele" then
					local key = table.find(user_see_no_evil,key_word)
					if key then
						table.remove(user_see_no_evil,key)
					end
					key = table.find(mod.ShenheSeeNoEvil,key_word)
					if key then
						table.remove(mod.ShenheSeeNoEvil,key)
						mod:notify(mod:localize("shenhe_dele_key_word",key_word))
					end
				end
			end
			mod.shenhe_unhappy_names = {}
			mod:set("shenhe_unhappy_words",user_see_no_evil)
			mod:notify(mod:localize("shenhe_refresh_key_word"))
		end
	end
end)

mod.shenhe_happiness_sekai_id = function(profile, name, is_account)
	local me = profile and Managers and Managers.player and profile == Managers.player:local_player(1)._profile
	local bot = not profile or not profile.character_id or string.find(profile.character_id, "^bot_")
	local chara_select = Managers and Managers.ui and Managers.ui:view_active("main_menu_view")
	if (me or chara_select) and mod.shenhe_id.me == "custom" then
		return mod.shenhe_id.myid or name
	end
	
	if ((me or chara_select) and mod.shenhe_id.me == "disable") or (not me and not mod.shenhe_id.others) or bot then
		return name
	end

	if not mod.shenhe_unhappy_names[name] then
		local shenhe_happy_name = name
		if mod.ShenheSeeNoEvil and not table.is_empty(mod.ShenheSeeNoEvil) then
			for k,key_word in pairs(mod.ShenheSeeNoEvil) do
				shenhe_happy_name = string.gsub(shenhe_happy_name,key_word,mod.shenhe_id_filtered or "申")
			end
			mod.shenhe_unhappy_names[name] = shenhe_happy_name
		else
			return name
		end
	end
	return mod.shenhe_unhappy_names[name]
end

-- all names (including mine) in Social & chat, during end-of-match
mod:hook(CLASS.PlayerInfo, "character_name", function(func, self)
    return mod.shenhe_happiness_sekai_id(self:profile(), func(self))
end)

-- all account names (including mine) in Social, during end-of-match
mod:hook(CLASS.PlayerInfo, "user_display_name", function(func, self)
    return mod.shenhe_happiness_sekai_id(self:profile(), func(self))
end)

-- over their heads in hub, used all over throughout a match, INCLUDING BOTS
mod:hook(CLASS.RemotePlayer, "name", function(func, self)
    return mod.shenhe_happiness_sekai_id(self._profile, func(self))
end)

-- my name in lower-left HUD
mod:hook(CLASS.HumanPlayer, "name", function(func, self)
    return mod.shenhe_happiness_sekai_id(self._profile, func(self))
end)

mod:hook(CLASS.BotPlayer, "name", function(func, self)
    return mod.shenhe_happiness_sekai_id(self._profile, func(self))
end)

mod:hook(CLASS.RemotePlayer, "character_name", function(func, self)
    return mod.shenhe_happiness_sekai_id(self._profile, func(self))
end)

-- when inviting, joining parties
mod:hook(CLASS.PresenceEntryImmaterium, "character_name", function(func, self)
    return mod.shenhe_happiness_sekai_id(self:character_profile(), func(self))
end)

-- when inviting, joining parties
mod:hook(CLASS.PresenceEntryMyself, "character_name", function(func, self)
    return mod.shenhe_happiness_sekai_id(self:character_profile(), func(self))
end)

-- in pre-mission lobby & character select
mod:hook_require("scripts/utilities/profile_utils", function(instance)
    mod:hook(instance, "character_name", function(func, profile)
        return mod.shenhe_happiness_sekai_id(profile, func(profile))
    end)
end)