setup.items ??= {};

setup.items['condom'] = {
	label: 'Condom',
	image:'locations/pavlovsk/market/condoms.jpg',
	desc: 'Protects you against STDs and unwanted pregnancies. The later has a risk of failing, which is higher if the person who puts the condom on is inexperienced. Also, condoms from some sources are of low quality and have an increased risk of failing.'
}
setup.items['cosmetics'] = {
	label: 'Make-up',
	image: 'pc/items/makeup.jpg',
	desc:"This collection of makeup consists of a diverse assortment of cosmetic products designed to enhance one's appearance. It encompasses a wide range of items such as foundations, concealers, eyeshadows, lipsticks, blushes, mascaras, and more.<br/>Applying light make-up consumes one use, medium make-up consumes two uses and more than that requires you to use three uses.<br/>You can buy more make-up at the super market."
}
setup.items['food'] = {
	label: 'Regular food',
	image: 'pc/items/food.jpg',
	desc: "Various different ingredients for the preparation of a meal, such as vegetables, meat and spices. While healthy, you won't be able to use them to cook something that is both filling and makes you lose weight."
}
setup.items['foodDiet'] = {
	label: 'Diet food',
	image: 'pc/items/foodDiet.jpg',
	desc: "Mostly consisting of exotic fruits and vegetables, these ingredients allow you to create meals which are healthy and filling, while allowing you to lose weight."
}
setup.items['hairPin'] = {
	label: 'Hair Pin',
	image: 'pc/items/hairPins.webp'
}
setup.items['hairScrunchie'] = {
	label: 'Hair Scrunchie',
	image: 'pc/items/srunchies.jpg'
}
setup.items['lipbalm'] = {
	label: 'Lipbalm',
	image: 'pc/items/lipbalm.jpg'
}

setup.items['razor'] = {
	label: 'Razor',
	image: 'pc/items/razor.png',
	desc:"A shaving tool specifically designed for hair removal. It features a single, sharp blade enclosed within a protective housing. It offers a simple and convenient temporary solution for achieving smooth skin.<br/>To shave your legs and your pubic hair, you need one razor each.<br/>You can buy new razors in the cosmetics department of a super market."
}
setup.items['refillable_bottle'] = {
	label: 'Refillable Bottle',
	image: 'pc/items/refillablebottle.jpg',
	desc:"<<gs 'RefillableBottleDescription'>>",
	limit: 1,
	passage:"RefillableBottle"
}
setup.items['sanpad'] = {
	label: 'Sanitary Pad',
	image: 'pc/items/sanpad.webp',
	desc:"Sanitary pads, also known as menstrual pads or sanitary napkins, are absorbent products designed to be worn by women during their menstrual cycle. They are made of a soft, absorbent material that helps to capture and contain menstrual blood. The pad has an adhesive backing to secure it to the inner lining of undergarments, providing comfort and preventing leakage."
}
setup.items['shampoo'] = {
	label: 'Shampoo',
	image: 'pc/items/shampoo.jpg'
}
setup.items['sunblock'] = {
	label: 'Sunblock',
	image: 'pc/items/sunblock.jpg',
	desc:"Used for protecting the skin against sunburns and premature aging during sunbathing.<br/>One potion of sunblock lasts for 30 minutes. You will automatically apply it before sunbathing if you have it with you.<br/>You can buy additional sunblock in the cosmetics department of a super market."
}
setup.items['tampon'] = {
	label: 'Tampon',
	image: 'pc/items/tampon.jpg',
	desc:"Tampons are feminine hygiene products designed to be inserted into the vagina during menstruation. They offer discreet and convenient menstrual protection, absorbing menstrual fluid to help keep individuals feeling clean and comfortable. They are equipped with a string or cord for easy removal.<br/>During your menstruation, you need to change your tampon at least once a day.<br/>You can buy new tampons at the pharmacy. You could also ask other females for one in case of an emergency."
}
setup.items['umbrella'] = {
	label: 'Umbrella',
	image: 'pc/items/umbrella.webp',
	limit: 1,
	desc: 'Protects you against rain and ensures that your hair and make-up don\'t get ruined.'
};
setup.items['vitamin'] = {
	label: 'Vitamin Pills',
	image: 'pc/items/vitamin.jpg'
}

class Inventory{

	
	_containers = {'default':{}}

	clear(){
		this._containers = {'default':{}};
	}

	// ----- Common Functions -----
	dec(item,count=1,container='default'){
		this.inc(item,count * -1,container);
	}

	
	/**
	 * Empties a container.
	 * @param {string} [container='default']
	 */
	empty(container: string='default'){
		this._containers[container] = {};
	}

	/**
	 * 
	 * @param {string} item  The ID of the item
	 * @param {string} container  The container
	 * @returns {number} The number of items of the type item in the container
	 */
    get(item,container='default'){
        return this._containers?.[container]?.[item]?.count || 0;
    }
    inc(item,count=1,container='default'){
        let current = this.get(item,container);
        this.set(item,current+count);
    }
    set(item:string,count=1,container='default',metadata=undefined){
		this._containers[container] ??= {}

		if(count == 0){
			//Remove data in the course.
			this._containers[container][item] = {count: 0};
			return;
		}

		this._containers[container][item] = {count: Math.max(0,count)};
		if(metadata)
			this.metadataUpdate(item,container,metadata);
    }

	itemsInContainer(container='default',includeZeroCount=true){
		let containerData = this._containers?.[container] || {};
		let result = {};
		for (const itemId of Object.keys(containerData)) {
			if(includeZeroCount || this.get(itemId,container) > 0)
				result[itemId] = this.metadata(itemId,container);
		}
		return result;
	}

	// ----- Metadata -----
	itemsInContainerByMetadata(filters,container='default',includeZeroCount=false){
		let itemsInContainer = this.itemsInContainer(container,includeZeroCount);
		let itemsInContainerValues = Object.values(itemsInContainer) as Array<object>;
		return Object.fromEntries(itemsInContainerValues.filterByObject(filters).map(itemData=>([itemData["id"],itemData])));
	}

	metadata(item,container='default'){
		return Object.assign(
			{
				id:item,
				label:item,
				count:this.get(item,container)
			},
			this.metadataConst(item),
			this.metadataDynamic(item,container)
		);
	}

	/**
	 * Returns contant metadata from setup.
	 * @param {string} item ItemId
	 * @returns {object}
	 */
	metadataConst(item: string): ItemDefinition{
		let metadata = setup.items[item] ?? {label:item,image:''};
		metadata.label ??= item;
		return metadata;
	}

	metadataDynamic(item,container='default'){
		return this._containers?.[container]?.[item]?.data ?? {};
	}

	metadataSet(item,container='default',data){
		this._containers[container] ??= {};
		this._containers[container][item] ??= {count:1};
		this._containers[container][item].data = data;
	}

	metadataUpdate(item,container='default',data){
		let newData = Object.assign({},this.metadataDynamic(item,container),data);
		this.metadataSet(item,container,newData);
	}

	moveToContainer(itemId,container,destinationContainer){
		this._containers[destinationContainer] ??= {};
		this._containers[destinationContainer][itemId] = this._containers[container][itemId];
		delete this._containers[container][itemId];;
	}

	moveToContainerAll(containerSrc,containerDest){
		this._containers[containerDest] = this._containers[containerSrc];
		this._containers[containerSrc] = {};
	}

	_init(Inventory){
		Object.keys(Inventory).forEach(function (pn) {
			this[pn] = clone(Inventory[pn]);
		}, this);

		return this;
	}

	clone = function () {
		return (new setup.Inventory())._init(this);
	};

	toJSON = function () {
		var ownData = {};
		Object.keys(this).forEach(function (pn) {
			if(typeof this[pn] !== "function")
				ownData[pn] = clone(this[pn]);
		}, this);
		return JSON.reviveWrapper('(new setup.Inventory())._init($ReviveData$)', ownData);
	};
}

setup.Inventory = Inventory;
