//       _________ __                 __
//      /   _____//  |_____________ _/  |______     ____  __ __  ______
//      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
//      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ |
//     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
//             \/                  \/          \//_____/            \/
//  ______________________                           ______________________
//                        T H E   W A R   B E G I N S
//         Stratagus - A free fantasy real time strategy game engine
//
//      (c) Copyright 1999-2022 by Vladi Belperchinov-Shabanski,
//		Jimmy Salmon and Andrettin
//
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; only version 2 of the License.
//
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
//      02111-1307, USA.

#pragma once

#include "database/data_type.h"
#include "database/named_data_entry.h"
#include "economy/resource_container.h"

class CGraphic;
struct lua_State;

static int CclDefineDefaultResourceNames(lua_State *l);
static int CclDefineResource(lua_State *l);

/**
**  Indices into costs/resource/income array.
*/
enum CostType {
	TimeCost,                               /// time in game cycles

	// standard
	CopperCost,                             /// copper resource
	WoodCost,                               /// wood  resource
	OilCost,                                /// oil   resource
	// extensions
	IronCost,								/// iron resource
	StoneCost,								/// stone resource
	CoalCost,								/// coal resource

	ResearchCost,							/// research resource
	PrestigeCost,							/// prestige resource
	GoldCost,                               /// gold resource
	SilverCost,								/// silver resource
	MithrilCost,							/// mithril resource
	LimestoneCost,							/// limestone resource
	JewelryCost,							/// jewelry resource
	FurnitureCost,							/// furniture resource
	LeatherCost,							/// leather resource
	DiamondsCost,							/// diamonds resource
	EmeraldsCost,							/// emeralds resource
	LeadershipCost,							/// leadership resource
	TradeCost,								/// trade resource, generated by trader units (converted to copper when delivered)

	MaxCosts                                /// how many different costs
};

constexpr int FoodCost = MaxCosts;
constexpr int ScoreCost = MaxCosts + 1;
constexpr int ManaResCost = MaxCosts + 2;
constexpr int PopulationCost = MaxCosts + 3;

namespace wyrmgus {

class resource_icon;

class resource final : public named_data_entry, public data_type<resource>
{
	Q_OBJECT

	Q_PROPERTY(int index READ get_index CONSTANT)
	Q_PROPERTY(wyrmgus::resource_icon* icon MEMBER icon READ get_icon NOTIFY changed)
	Q_PROPERTY(int default_income MEMBER default_income READ get_default_income)
	Q_PROPERTY(int default_amount MEMBER default_amount READ get_default_amount)
	Q_PROPERTY(wyrmgus::resource* final_resource MEMBER final_resource)
	Q_PROPERTY(int final_resource_conversion_rate MEMBER final_resource_conversion_rate READ get_final_resource_conversion_rate)
	Q_PROPERTY(int base_price MEMBER base_price READ get_base_price)
	Q_PROPERTY(int demand_elasticity MEMBER demand_elasticity READ get_demand_elasticity)
	Q_PROPERTY(wyrmgus::resource* input_resource MEMBER input_resource)
	Q_PROPERTY(bool main READ is_main CONSTANT)
	Q_PROPERTY(bool luxury MEMBER luxury READ is_luxury NOTIFY changed)
	Q_PROPERTY(bool special MEMBER special READ is_special NOTIFY changed)
	Q_PROPERTY(bool hidden MEMBER hidden READ is_hidden)
	Q_PROPERTY(QString conversion_rates_string READ get_conversion_rates_qstring CONSTANT)

public:
	static constexpr const char *class_identifier = "resource";
	static constexpr const char *database_folder = "resources";

	static const std::vector<resource *> &get_main_resources()
	{
		return resource::main_resources;
	}

	static const std::vector<const resource *> &get_luxury_resources()
	{
		return resource::luxury_resources;
	}

	static int get_price(const resource_map<int> &costs);
	static int get_mass_multiplier(const uint64_t mass, const uint64_t base_mass);

private:
	static inline std::vector<resource *> main_resources;
	static inline std::vector<const resource *> luxury_resources;

public:
	explicit resource(const std::string &identifier) : named_data_entry(identifier)
	{
	}

	virtual void process_gsml_property(const gsml_property &property) override;
	virtual void initialize() override;
	virtual void check() const override;

	int get_index() const
	{
		return this->index;
	}

	resource_icon *get_icon() const
	{
		return this->icon;
	}

	const std::string &get_action_name() const
	{
		return this->action_name;
	}

	int get_default_income() const
	{
		return this->default_income;
	}

	int get_default_amount() const
	{
		return this->default_amount;
	}

	const resource *get_final_resource() const
	{
		if (this->final_resource != nullptr) {
			return this->final_resource;
		}

		return this;
	}

	bool is_final() const
	{
		return this->get_final_resource() == this;
	}

	int get_final_resource_conversion_rate() const
	{
		return this->final_resource_conversion_rate;
	}

	int get_base_price() const
	{
		return this->base_price;
	}

	int get_demand_elasticity() const
	{
		return this->demand_elasticity;
	}

	bool IsMineResource() const;

	const resource *get_input_resource() const
	{
		return this->input_resource;
	}

	bool is_main() const;

	bool is_luxury() const
	{
		return this->luxury;
	}

	bool is_special() const
	{
		return this->special;
	}

	bool is_hidden() const
	{
		return this->hidden;
	}

	const std::vector<const resource *> &get_child_resources() const
	{
		return this->child_resources;
	}

	std::string get_conversion_rates_string() const
	{
		std::string str;

		bool first = true;
		for (const wyrmgus::resource *child_resource : this->get_child_resources()) {
			if (child_resource->get_index() == TradeCost || child_resource->is_hidden()) {
				continue;
			}

			if (!first) {
				str += "\n";
			} else {
				first = false;
			}

			str += child_resource->get_name();
			str += " Conversion Rate: ";
			str += std::to_string(child_resource->get_final_resource_conversion_rate());
			str += "%";
		}

		return str;
	}

	QString get_conversion_rates_qstring() const
	{
		return QString::fromStdString(this->get_conversion_rates_string());
	}

signals:
	void changed();

private:
	int index = -1;
	resource_icon *icon = nullptr;
	std::filesystem::path icon_file;
	std::string action_name;
	int default_income = 100;
	int default_amount = 1000;
public:
	int DefaultMaxAmount = -1;
private:
	resource *final_resource = nullptr;
	int final_resource_conversion_rate = 100;
	int base_price = 0;
	int demand_elasticity = 100;
	resource *input_resource = nullptr;
	bool luxury = false;
	bool special = false; //whether this is a special resource, i.e. whether it should not be shown among the main resources
	bool hidden = false;
	std::vector<const resource *> child_resources; //resources (other than this one) that have this resource as their final resource
public:

	friend int ::CclDefineDefaultResourceNames(lua_State *l);
	friend int ::CclDefineResource(lua_State *l);
};

}

/**
**  Default resources for a new player.
*/
extern int DefaultResources[MaxCosts];

/**
**  Default resources for a new player with low resources.
*/
extern int DefaultResourcesLow[MaxCosts];

/**
**  Default resources for a new player with mid resources.
*/
extern int DefaultResourcesMedium[MaxCosts];

/**
**  Default resources for a new player with high resources.
*/
extern int DefaultResourcesHigh[MaxCosts];

/**
**  Default names for the resources.
*/
extern std::string DefaultResourceNames[MaxCosts];

extern int GetResourceIdByName(const char *resourceName);
extern int GetResourceIdByName(lua_State *l, const char *resourceName);
