declare module "twine-sugarcube" {
	export interface SugarCubeSetupObject {
		Appearance: { new(playerCharacter: PlayerCharacter): Appearance };
		BodyDescription: { new(): BodyDescription };
		Consumable: { new(): Consumable };
		Drugs: { new(): Drugs };
		Events: { new(): Events };
		GameTime: { new(): GameTime };
		Inventory: { new(): Inventory };
		Location:{ new(): GameLocation };
		LocationIdentifier:{ new(): LocationIdentifier };
		Mood: { new(): Mood };
		Moodlet: { new(): Moodlet };
		MoodletGroup: { new(): MoodletGroup };
		Pain: { new(): Pain };
		PlayerCharacter: { new(): PlayerCharacter };
		Quest: {
			handler: object; new(questId?: any): Quest 
		};
		QuestsDict: { new(): QuestsDict };
		Skill: { new(): Skill };
		VersionControl: { new(): VersionControl };

		appearanceModificators: { [key: string]: any; };
		consumables: { [key: string]: ConsumableDefinition;}
		deco: { [key: string]: { [key: string]: any; }}
		drugs: { [key: string]: DrugDefinition}
		effects: { [key: string]: { [key: string]: any; }}
		consumableMenus:{ [key: string]: ConsumableMenuDefinition}
		items: { [key: string]: ItemDefinition; };
		jobs: { [key: string]: JobDefinition};
		locations: { [key: string]: LocationDefinition; };
		moodlets: { [key: string]: Moodlet; };
		moodletGroups: { [key: string]: MoodletGroup; };
		painReasons:  {[key: string]: { [key: string]: any; }}
		skills: { [key: string]: SkillDefinition; };
		startingCharacters: {[key: string]: StartCharacterDefinition};

		crimeLikelihood: (crimeId:string,location:LocationIdentifier)=>number;
		durationToString: any;
		func: (passage: string, ...arguments: Array<string|number>)=>any;
		getBodyparts: any;
		getBodypart:any;
		getConsumable: (type:string)=>{ [key: string]: any; };
		getConsumableMenu: (id:string)=>ConsumableMenuDefinition;
		getDeco: (type:string,position:string,id:number|string)=>{ [key: string]: any; };
		getDrug: (type:string)=>DrugDefinition;
		getDecoPosition: (type:string,position:string) => { [key: string]: any; }
		getDecoPositions: (type:string)=>string[];
		getEffect: (type:string)=>{ [key: string]: any; };
		getLocation: (locationId: string)=>LocationDefinition;
		getStartingCharacter: (type:string)=>StartCharacterDefinition;
		getStartingCharactersByFilter: (filters:{},shallow:boolean)=>{};

		makeSVG: (tag:string, attrs:any,innerHTML?:string|number|undefined) => SVGElement;
		mediaPath(rawPath:string):string;
		mediaPathImage(rawPath:string):string;
		mergeDeep: (target:any, ...sources:any) => any;

		randomName: (type:string)=>string;

		startingCharacterApply:(id:string)=>void;
		startingCharacterTagsIncludes:(tag:string)=>boolean;
		
		/**
		 * Returns whether the place the playercharacter currently is at has internet access.
		 * @returns {boolean}
		 */
		hasInternet(): boolean;

		settingsApply:(settings: any)=>void;
		weekDayIntToString: any;
		worldSettings:any;

		isWebVersion:boolean;


		skillHistoryDrawGraph(domElementId:string,skillID:string):void;
	}
	
	export interface SugarCubeStoryVariables {
		events: Events;
		finances: any;
		housing:any;
		inventory: Inventory;
		jobs: any;
		location: GameLocation;
		npcs:any;
		pc: PlayerCharacter;
		q: QuestsDict;
		settings:any;
		startCharacter: string;
		time: GameTime;
		wardrobe:any;
		
		
		ARGS: Array<string>;
		connectedLocations: ConnectedLocation[];
		eventReturnLocation: LocationIdentifier;
		here: string;
		location_var: object;
		media_path: string;
		quest: (id:string)=>Quest;
		result: number | string;
		/**
		 * The version of the game. Format is xxxxxxx.xx.xx.
		 * @type {number}
		 * @example
		 * version = 10345; //1.3.45
		 */
		version: number;
	}

	
	
}

declare global {
	export interface Array<T>{
		fancyMathEvaluate(): number;
		filterByObject(filter: object): Array<T>;

		isConsecutive(stepSize?:number): boolean;
	}

	interface Math {
		ceilAbs: (n:number)=>number;
		logBase: (n:number, base:number)=>number;
	}

	export class Util{
		static slugify(s:string): string;
	}

	export interface Window{
		rand(x:number,y:number): number;
	}


	export interface StartCharacterDefinition{
			/**
			 * The description that's displayed to the player
			 * @type {?string}
			 */
			desc?:string

			finances?:{
				
				/**
				 * The starting cash of the character.
				 * @type {?number}
				 */
				cash?:number
			},

			housing?:{
				home?: string
			},

			/**
			 * Obvious things are obvious
			 * @type {?string}
			 */
			image?:string

			
			/**
			 * Used internally in `setup.getStartingCharacter`. Don't overwrite.
			 * @type {?string[]}
			 */
			inheritance?:string[]

			items?:{
				[key: string]: number | {
						generateFunction:string,
						generateParameters?:any[]
					}
				
			}

			
			/**
			 * What is displayed to the player
			 * @type {?string}
			 */
			label?:string

			location?:{
				[key: string]:{
					[key: string]:any
				}
			}

			locationTags?:{
				[key: string]:{
					[key: string]:any
				}
			}

			npcs?:{
				bulk?:{
					[key: string]:{
						values?:{
							rel?:number,
							fam?:number
						},
						filters?:{
							[key: string]:any
						}
					}
				}
				[key: string]: any
			}
			
			
			/**
			 * Another character defintion that is to be inherited.
			 * @type {?string}
			 */
			parent?:string

			/**
			 * Starting values of the PlayerCharacter. Every field of this class can be overwritten.
			 * @type {?{ [key: string]: any; }}
			 */
			pc?:{ [key: string]: any; }

			quests?:{
				[key: string]: boolean;
			}

			school?:{
				[key: string]: any;
			}

			skills?:{
				[key: string]: number;
			}

			
			/**
			 * Categories of the starting character.
			 * @type {string[]}
			 */
			tags?:string[]

			time?: any;

			traits?:{
				[key: string]: number;
			}
			wardrobe?:{
				itemsByFilter?:{
					[key: string]:{
						filters?:{
							[key: string]:any;
						};
						count?: number;
						action?: 'add'|'wear';
					}
				},
				items?:{
					[key: string]:'add'|'wear';
				}
			};
	}

	export interface ConnectedLocation{
		forPassage : string,
		targetPassage: string,
		targetArguments: undefined,
		label: string,
		image: string,
		duration: number,
		class: string,
		priority: number,
		content: string,
		hotkeys: any,
		indecencyBlocked?:boolean,
		capturedVars: {[key:string]:any};
	}

	export interface ConsumableDefinition{
		alcohol?:number;

		costItems?:string[];

		desc?:string;

		
		/**
		 * Relative calories with 1 being an healthy amount.
		 * @type {?number}
		 */
		energy?:number;

		hunger?: number;

		image?: string;
		imageRand?: ImageRand;

		label?:string;

		moodletIds?:string[];

		price?: number;
		
		thirst?:number;

		/**
		 * The time it takes to consume.
		 * @type {number}
		 */
		time:number;
		type: 'drink'|'meal'|'candy';
	}
	
	export interface ConsumableMenuDefinition{
		payment:'cash'|'bank'|'both';
		categories:{
			[key:string] : {
				label:string;
				items:{
					[key:string] : {
						
						/**
						 * Overwrites the original items price with a flat number. In case of a function, the original price is taken as input. `Math.round()` is always applied to the result then.
						 * @type {(number|((n:number)=>number))}
						 */
						price?:number|((n:number)=>number);
					}
				}
			}
		}
	}

	export interface DrugDefinition{
		deterioration: number;
		effects:{[key: string]:{condition:any; effect:string;}};

		byproduct?:DrugByproductDefinition;
		
		/*{
			buildup: 1.5,
			deterioration: 0.0017,
			effects:{
				hangover:{
					condition:{mainEffectsInactive:true},
					effect: 'hangover'
				}
			}
		}*/
	}

	export interface DrugByproductDefinition extends DrugDefinition{
		buildup: number;
	}

	export interface DrugInCharacter{
		vol:number;byproduct?:number;
	}

	export interface ImageRand{

	}


	export interface ItemDefinition{
		
		
		/**
		 * An optional description to be displayed to the player.
		 * @type {?string}
		 */
		desc?: string;

		
		/**
		 * Information on how the item behaves if used as furniture.
		 * @type {?object}
		 */
		furniture?:object;

		/**
		 * Path to the image of the item.
		 * @type {string}
		 */
		image:string;

		/**
		 * The label that's displayed to the player. Defaults to the id of the item.
		 * @type {?string}
		 */
		label?:string;

		
		/**
		 * How many items of the same type fit into a purse.
		 * @type {?number}
		 */
		limit?:number;

		
		/**
		 * A passage the player is sent to when he clicks the item in the inventory.
		 * @type {?string}
		 */
		passage?:string;

		
		/**
		 * Default price.
		 * @type {?number}
		 */
		price?: number;
		
	}

	export interface JobDefinition{

	}

	export interface LocationDefinition{
		openTimes?:TimespanIdentifier;
	}

	export interface TimespanIdentifier{
		days?: ('MO'|'TU'|'WE'|'TH'|'FR'|'SA'|'SU'|'work')[];
		daysBL?: ('MO'|'TU'|'WE'|'TH'|'FR'|'SA'|'SU'|'work')[];
		holiday?:boolean;
		vacation?:boolean;
		begin?:number[];
		end?:number[];
	}

	export interface SkillDefinition{
		
		label ?: string;
		description?:string;
		descibtionByLevel?:{[key:number]: string};
		image?:string;
		
		/**
		 * Hide this skill from players in overviews when set to true.
		 * @type {?boolean}
		 */
		hidden?: boolean;

		/**
		 * A function that provides a skill level.
		 * @type {(skillLevel:number)=>number} Experience
		 */
		e2s?: (skillLevel:number)=>number;

		/**
		 * A function that provides a number of required skillpoints.
		 * @type {(skillLevel:number)=>number} Skill Level
		 */
		s2e?: (skillLevel:number)=>number;
	}
	
	export interface SkillOfCharacter{
		
		
		/**
		 * The maximum number the experience can reach. 0 if disabled.
		 * @type {number}
		 */
		ceil:number;
		
		/**
		 * Current number of experience points.
		 * @type {number}
		 */
		experience:number;

		
		/**
		 * History of this skill for the last days.
		 * @type {number[]}
		 */
		experienceHistory:number[];

		
		/**
		 * The minimum number the experience can reach.
		 * @type {number}
		 */
		floor: number;

		/**
		 * The last daystart this skill has been used.
		 * @type {number}
		 */
		lastUsed: number;
	}

	

}


export { };