setup.houses ??= {};

class Housing{

    _access = [];

    _home = '';  // Home is where all your stuff is
    get home(){return this._home;}
    set home(v){
        this._home = v;

		const houseData = this.houseData(v);
		if(houseData.ownership == 'rent')
			this.startRent(v);
		else
        	this.addAccess(v);

        console.log("Home set",v);
    }

    get homeLocation(){
        return this.houseData(this.home).location;
    }

    addAccess(houseId){
        this._access.pushUnique(houseId);
    }

    hasAccess(houseId){
		if(this.rentActiveIds.includes(houseId))
			return true;
        return this._access.includes(houseId);
    }

    house(houseId){
		if(typeof houseId == "object"){
			let houseData = houseId;
			if(houseData.id)
				houseData = setup.mergeDeep({},houseData,this.houseData(houseId));
			return new setup.House(houseData);
		}
			

		
		return new setup.House(this.houseData(houseId));
    }

	houseData(houseId){
		return setup.mergeDeep(
			{},
			this.houseData_static(houseId),
			this.houseData_dynamic(houseId),
		);
	}

	houseData_static(houseId){
		return setup.houses[houseId] ?? {};
	}

    isHome(houseId){
        return (this.home == houseId);
    }


	// ----- Dynamic House Data -----
	_houses = {};

	houseData_dynamic(houseId){
		return (this._houses[houseId] ?? {});
	}

	register(houseId,data={}){
		this.set(houseId,data,true);
	}

	set(houseId,data={},replace=false){
		if(replace)
			this._houses[houseId] = clone(data);
		else
			this._houses[houseId] = setup.mergeDeep({},this.houseData_dynamic(houseId),data);
	}

	// ----- Connections -----
	_connections = {};

	get activeConnections(){
		let result = {};
		for(const activeConnectionsId of this.activeConnectionsIds){
			result[activeConnectionsId] = this._connections[activeConnectionsId];
		}
		return result;
	}

	get activeConnectionsIds(){
		return Object.values(this.rents).map(entry=>entry.rent.connections).flat();
	}

	connectionsByFromPassage(fromPassage){
		return Object.values(this.activeConnections).filter((connection) => connection.fromPassage == fromPassage);
	}

	registerConnection(id,fromPassage,toPassage,passageArg,label,time,image,flags={}){
		this._connections[id] = {
			id: id,
			fromPassage:fromPassage,
			toPassage:toPassage,
			passageArg:passageArg,
			label:label,
			time:time,
			image:image,
			flags:flags
		}
	}

	registerConnections(connections,prefix){
		var result = [];
		for (const [connectionId,connectionData] of Object.entries(connections)) {
			const id = prefix + connectionId;
			this._connections[id] = connectionData;
			result.push(id);
		}
		return result;
	}

	// ----- Rent -----
	_rent = {};

	rentExpirationTime(rentId){
		return this._rent[rentId]?.expirationTime ?? State.variables.time.endTime;
	}

	rentIsActive(rentId){
		if(this._rent[rentId]){
			if(this._rent[rentId].expirationTime)
				return State.variables.time.isFuture(this._rent[rentId].expirationTime);
			return true;
		}
		return false;
	}

	get rents(){
		return Object.fromEntries(
			this.rentActiveIds.map(
				id=>(
					[id,{data:this.houseData(id),rent:this._rent[id]}]
				)
			)
		);
	}

	get rentActiveIds(){
		return Object.keys(this._rent).filter(key=>this.rentIsActive(key));
	}

	startRent(propertyId,paymentPerMonth=undefined,expirationTime=undefined){
		
		/**
		 * @type {Finances}
		 */
		const finances = State.variables.finances;
		const houseData = this.houseData(propertyId);
		
		paymentPerMonth ??= houseData.rent;

		// ---- Rent Payments ----
		const transaction_id = `rent_${propertyId}_pay`;
		finances.bankScheduledTransactionsRegister(transaction_id,-paymentPerMonth,'nth of month',undefined,undefined,`Rent payment for one month`);

		// ---- Connections -----
		const connection_prefix = `rent_${propertyId}_`;
		const connectionsIds = this.registerConnections(houseData.connect,connection_prefix);

		this._rent[propertyId] = {
			pay: paymentPerMonth,
			transaction: transaction_id,
			connections: connectionsIds,
			expirationTime: expirationTime
		};
	}

    constructor(){}

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

        return this;
    }

    clone = function () {
        return (new setup.Housing())._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.Housing())._init($ReviveData$)', ownData);
    };
}

setup.Housing = Housing;

class House{

	room(roomId){
		let roomData = this.rooms[roomId] ?? {};
		if(roomData.template){
			roomData = setup.mergeDeep(
				{},
				roomData,
				this.roomTemplateData(roomData.template),
			);
		}
		return roomData;
	}

	roomExists(roomId){
		return !(!this.rooms[roomId]);
	}

	roomTemplateData(roomTemplateId){
		return setup.rooms[roomTemplateId] ?? {};
	}

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

setup.House = House;
