/*
 * Copyright (c) 2024 Marco Cawthorne <marco@icculus.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

// SCIENTISTS WILL ATTACK EACH OTHER AS WELL AS
// PLAYERS. THEY ARE BASICALLY ALL ROGUE.
//
// IF A SCIENTIST KILLS NPCS OR PLAYERS
// IT WILL PLAY SH/HIDE_LAUGH.WAV
//
// THEY CAN ALSO RESPAWN

#pragma PROGS_DAT  "../../zpak001.pk3dir/progs/madness.dat"

#include "../../../src/server/api.h"
#include "arsenal.h"
#include "scimanager.h"
#include "shared.h"

/* Slaughter is the default game mode. */


void
CodeCallback_Input(entity activator, string inputName, string dataString)
{
	switch (inputName) {
#if 0
	case "CountScientists":
		int livingScientists = 0i;
		for (entity s = world; (s = find(s, ::classname, "monster_scientist"));) {
			if (s.solid == SOLID_BBOX || s.solid == SOLID_SLIDEBOX) {
				livingScientists++;
			}
		}

		serverinfo.SetInteger("sci_count", livingScientists);
		break;
#endif
	case "ScientistKilled":
		activator.frags += 1;
		break;
	case "ScientistDied":
		ScientistManager::RespawnSingle(activator, 10.0f);
		break;
	}
}

void
CodeCallback_StartGameType(void)
{
	SHArsenal_Init();
	motd.LoadDefault();

	teams.SetUp(1, "Players", [153, 204, 255], true);
	teams.SetSpawnPoint(1, "info_player_team1");
	teams.SetUp(4, "Scientists", [153, 204, 255], true);
	teams.SetSpawnPoint(2, "monster_scientist");

	precache_sound("sh/hide_laugh.wav");

// 	game.SetSpawnPoint("info_player_team1");
	ScientistManager::PopulateLevel(cvars.GetInteger("sh_scimax"), "sh_scientist_madness");
}

void
CodeCallback_PlayerSpawn(entity playerEntity)
{
	string playerModel;

	ents.ChangeToClass(playerEntity, "player_slaughter");
	ents.Input(playerEntity, "SetTeam", "1", playerEntity);

	/* interpret the 'model' InfoKey */
	playerModel = userinfo.GetString(playerEntity, "model");

	if (playerModel != "") {
		playerModel = sprintf("models/player/%s/%s.mdl", playerModel, playerModel);
	}

	/* fallback is always models/player.mdl for Half-Life */
	if (playerModel == "" || exists.InVFS(playerModel) == false) {
		playerModel = "models/player.mdl";
	}

	playerEntity.modelindex = getmodelindex(playerModel); /* keep OG size */
	game.TeleportToSpawn(playerEntity);
	SHArsenal_GiveItemsToPlayer(playerEntity);
}


void
CodeCallback_PlayerDisconnect(entity playerEntity)
{

}

bool
CodeCallback_PlayerRequestRespawn(entity playerEntity)
{
	CodeCallback_PlayerSpawn(playerEntity);
	return (true);
}

void
CodeCallback_PlayerDamage(entity playerEntity, entity inflictor, entity attacker)
{

}

.bool WASPOISONED;

void
CodeCallback_PlayerKilled(entity playerEntity, entity inflictor, entity attacker, string weapon)
{
	/* Only laugh when the target wasn't poisoned, TODO */
	if (attacker.classname == "sh_scientist_madness" && playerEntity.WASPOISONED == false) {
		sound(attacker, CHAN_AUTO, "sh/hide_laugh.wav", 1.0, ATTN_NORM);
	}

	combat.Obituary(playerEntity.netname, attacker.netname, weapon, "");

	/* death-counter */
	playerEntity.deaths++;

	/* update score-counter */
	if (ents.isPlayer(attacker)) {
		if (playerEntity == attacker) {
			attacker.frags--;
		} else {
			attacker.frags++;
		}
	}
}

bool
CodeCallback_ClientCommand(entity playerEntity, string command)
{
	float commandArgs = tokenize(command);

	switch (argv(0)) {
	default:
		return (false);
	}

	return (true);
}

bool
CodeCallback_ImpulseCommand(entity playerEntity, float impulseNum)
{
	switch (impulseNum) {
	case 100:
		if (AllowFlashlight() == true) {
			ents.Input(playerEntity, "UseItem", "item_suit", playerEntity);
		}
		break;
	default:
		return (false);
	}

	return (true);
}
