#include "ShipSpecialStatsDialogModel.h"
namespace fso {
	namespace fred {
		namespace dialogs {
			ShipSpecialStatsDialogModel::ShipSpecialStatsDialogModel(QObject* parent, EditorViewport* viewport)
				: AbstractDialogModel(parent, viewport)
			{
				initializeData();
			}

			void ShipSpecialStatsDialogModel::initializeData()
			{
				object* objp;
				num_selected_ships = 0;
				m_selected_ships.resize(MAX_SHIPS);

				objp = GET_FIRST(&obj_used_list);
				while (objp != END_OF_LIST(&obj_used_list)) {
					if ((objp->type == OBJ_START) || (objp->type == OBJ_SHIP)) {
						if (objp->flags[Object::Object_Flags::Marked]) {
							m_selected_ships[num_selected_ships] = objp->instance;
							num_selected_ships++;
						}
					}
					objp = GET_NEXT(objp);
				}

				m_ship = _editor->cur_ship;
				//Special Hits
				if (Ships[m_ship].special_hitpoints) {
					m_hull = Ships[m_ship].special_hitpoints;
					m_special_hitpoints_enabled = true;
				}
				else {
					ship_info* sip;
					sip = &Ship_info[Ships[m_ship].ship_info_index];

					m_hull = static_cast<int>(sip->max_hull_strength);
					m_special_hitpoints_enabled = false;

					if (m_hull < 1) { m_hull = 10; }
				}

				if (Ships[m_ship].special_shield > 0) {
					m_shields = Ships[m_ship].special_shield;
					m_special_shield_enabled = true;
				}
				else {
					// get default_table_values
					ship_info* sip;
					sip = &Ship_info[Ships[m_ship].ship_info_index];

					m_shields = static_cast<int>(sip->max_shield_strength);
					m_special_shield_enabled = false;

					if (m_shields < 0) {
						m_shields = 0;
					}
				}

				//Special Explosions
				if (!(Ships[m_ship].use_special_explosion)) {
					// get default_table_values
					ship_info* sip;
					sip = &Ship_info[Ships[m_ship].ship_info_index];

					m_inner_rad = static_cast<int>(sip->shockwave.inner_rad);
					m_outer_rad = static_cast<int>(sip->shockwave.outer_rad);
					m_damage = static_cast<int>(sip->shockwave.damage);
					m_blast = static_cast<int>(sip->shockwave.blast);
					m_shockwave = static_cast<int>(sip->explosion_propagates);
					m_shock_speed = static_cast<int>(sip->shockwave.speed);
					m_deathRoll = false;
					m_duration = 0;
					m_special_exp = false;

					if (m_inner_rad < 1) {
						m_inner_rad = 1;
					}
					if (m_outer_rad < 2) {
						m_outer_rad = 2;
					}
					if (m_shock_speed < 1) {
						m_shock_speed = 1;
					}
				}
				else {
					m_inner_rad = Ships[m_ship].special_exp_inner;
					m_outer_rad = Ships[m_ship].special_exp_outer;
					m_damage = Ships[m_ship].special_exp_damage;
					m_blast = Ships[m_ship].special_exp_blast;
					m_shockwave = Ships[m_ship].use_shockwave;
					m_shock_speed = Ships[m_ship].special_exp_shockwave_speed;
					m_deathRoll = (Ships[m_ship].special_exp_deathroll_time > 0);
					m_duration = Ships[m_ship].special_exp_deathroll_time;
					m_special_exp = true;
				}
				modelChanged();
			}

			bool ShipSpecialStatsDialogModel::apply()
			{
				float temp_max_hull_strength;
				int new_shield_strength, new_hull_strength;
				if (m_special_hitpoints_enabled) {

					// Don't update anything if the hull strength is invalid
					if (m_hull < 1) {
						return false;
					}

					// set to update

					new_hull_strength = m_hull;
					//Ships[m_ship_num].special_hitpoints = m_hull;

				}
				else {
					// set to update

					new_hull_strength = 0;
				}

				if (m_special_shield_enabled) {

					// Don't update anything if the hull strength is invalid
					if (m_shields < 0) {
						return false;
					}

					// set to update

					new_shield_strength = m_shields;
					//Ships[m_ship_num].special_shield = m_shields;

				}
				else {
					// set to update

					new_shield_strength = -1;
				}

				if (m_inner_rad > m_outer_rad) {
					auto button = _viewport->dialogProvider->showButtonDialog(DialogType::Error, "Invalid Entry", "Inner radius must be less than outer radius",
						{ DialogButton::Ok });
					if (button == DialogButton::Ok) {
						return false;
					}
				}

				for (auto& shipp : m_selected_ships) {
					// set the special hitpoints/shield
					Ships[shipp].special_hitpoints = new_hull_strength;
					Ships[shipp].special_shield = new_shield_strength;

					// calc kamikaze stuff
					if (Ships[shipp].special_hitpoints)
					{
						temp_max_hull_strength = (float)Ships[shipp].special_hitpoints;
					}
					else
					{
						temp_max_hull_strength = Ship_info[Ships[shipp].ship_info_index].max_hull_strength;
					}

					Ai_info[Ships[shipp].ai_index].kamikaze_damage = std::min(1000, 200 + static_cast<int>(temp_max_hull_strength / 4.0f));

					if (m_special_exp) {
						// set em
						Ships[shipp].use_special_explosion = true;
						Ships[shipp].special_exp_inner = m_inner_rad;
						Ships[shipp].special_exp_outer = m_outer_rad;
						Ships[shipp].special_exp_damage = m_damage;
						Ships[shipp].special_exp_blast = m_blast;
						Ships[shipp].use_shockwave = (m_shockwave ? 1 : 0);
						if (m_shock_speed) {
							if (m_shock_speed < 1) {
								m_shock_speed = 1;
								_viewport->dialogProvider->showButtonDialog(DialogType::Warning, "Invalid Entry", "Shockwave speed must be defined! Setting this to 1 now",
									{ DialogButton::Ok });
							}
							Ships[shipp].special_exp_shockwave_speed = m_shock_speed;
						}
						if (m_duration) {
							if (m_duration < 2) {
								m_duration = 2;
								_viewport->dialogProvider->showButtonDialog(DialogType::Warning, "Invalid Entry", "Death roll time must be at least 2 milliseconds Setting this to 2 now",
									{ DialogButton::Ok });
							}
							Ships[shipp].special_exp_deathroll_time = m_duration;
						}
					}
					else {
						Ships[shipp].use_special_explosion = false;
						Ships[shipp].special_exp_inner = -1;
						Ships[shipp].special_exp_outer = -1;
						Ships[shipp].special_exp_damage = -1;
						Ships[shipp].special_exp_blast = -1;
						Ships[shipp].use_shockwave = false;
						Ships[shipp].special_exp_shockwave_speed = -1;
						Ships[shipp].special_exp_deathroll_time = 0;
					}
				}
				_editor->missionChanged();
				return true;
			}
			void ShipSpecialStatsDialogModel::reject()
			{
			}
			bool ShipSpecialStatsDialogModel::getSpecialExp() const
			{
				return m_special_exp;
			}
			void ShipSpecialStatsDialogModel::setSpecialExp(const bool value)
			{
				modify(m_special_exp, value);
			}
			bool ShipSpecialStatsDialogModel::getShockwave() const
			{
				return m_shockwave;
			}
			void ShipSpecialStatsDialogModel::setShockwave(const bool value)
			{
				modify(m_shockwave, value);
			}
			bool ShipSpecialStatsDialogModel::getDeathRoll() const
			{
				return m_deathRoll;
			}
			void ShipSpecialStatsDialogModel::setDeathRoll(const bool value)
			{
				modify(m_deathRoll, value);
			}
			int ShipSpecialStatsDialogModel::getDamage() const
			{
				return m_damage;
			}
			void ShipSpecialStatsDialogModel::setDamage(const int value)
			{
				modify(m_damage, value);
			}
			int ShipSpecialStatsDialogModel::getBlast() const
			{
				return m_blast;
			}
			void ShipSpecialStatsDialogModel::setBlast(const int value)
			{
				modify(m_blast, value);
			}
			int ShipSpecialStatsDialogModel::getInnerRadius() const
			{
				return m_inner_rad;
			}
			void ShipSpecialStatsDialogModel::setInnerRadius(const int value)
			{
				modify(m_inner_rad, value);
			}
			int ShipSpecialStatsDialogModel::getOuterRadius() const
			{
				return m_outer_rad;
			}
			void ShipSpecialStatsDialogModel::setOuterRadius(const int value)
			{
				modify(m_outer_rad, value);
			}
			int ShipSpecialStatsDialogModel::getShockwaveSpeed() const
			{
				return m_shock_speed;
			}
			void ShipSpecialStatsDialogModel::setShockwaveSpeed(const int value)
			{
				modify(m_shock_speed, value);
			}
			int ShipSpecialStatsDialogModel::getRollDuration() const
			{
				return m_duration;
			}
			void ShipSpecialStatsDialogModel::setRollDuration(const int value)
			{
				modify(m_duration, value);
			}
			bool ShipSpecialStatsDialogModel::getSpecialShield() const
			{
				return m_special_shield_enabled;
			}
			void ShipSpecialStatsDialogModel::setSpecialShield(const bool value)
			{
				modify(m_special_shield_enabled, value);
			}
			int ShipSpecialStatsDialogModel::getShield() const
			{
				return m_shields;
			}
			void ShipSpecialStatsDialogModel::setShield(const int value)
			{
				modify(m_shields, value);
			}
			bool ShipSpecialStatsDialogModel::getSpecialHull() const
			{
				return m_special_hitpoints_enabled;
			}
			void ShipSpecialStatsDialogModel::setSpecialHull(const bool value)
			{
				modify(m_special_hitpoints_enabled, value);
			}
			int ShipSpecialStatsDialogModel::getHull() const
			{
				return m_hull;
			}
			void ShipSpecialStatsDialogModel::setHull(const int value)
			{
				modify(m_hull, value);
			}
		}

	}
}