App.Neighbor.Interact = (function() {
	let nd = new App.Neighbor.Display((id) => replaceDetails(id));

	/** Output the arcology list
	 * @returns {DocumentFragment}
	 */
	function list() {
		V.arcologies.forEach((a) => a.prosperity = Math.clamp(a.prosperity, 1, 300));
		if (!V.activeArcologyIdx) {
			V.activeArcologyIdx = 0;
		}

		let frag = document.createDocumentFragment();

		// set up the neighbor display list itself
		frag.append(nd.render());
		$(document).one(':passagedisplay', () => nd.select(V.activeArcologyIdx));

		// empty container for details
		const detailSpan = App.UI.DOM.appendNewElement("span", frag);
		detailSpan.id = "neighbor-details";

		return frag;
	}

	/** Replace the details block with an updated one for the given arcology
	 * Used both as a refresh and as a selection handler
	 * @param {number} arcID
	 */
	function replaceDetails(arcID) {
		V.activeArcologyIdx = arcID;
		const container = $("#neighbor-details").empty();
		container.append(description(arcID));
		container.append(details(arcID));
	}

	/** Re-render most of the page because some important arcology property (FS, government, ownership) may have changed
	 * @param {number} arcID for reselection
	 */
	function arcChanged(arcID) {
		nd.rerender();
		nd.select(arcID);
	}

	/** Create a div containing the neighbor's description
	 * @param {number} arcID
	 * @returns {Element}
	 */
	function description(arcID) {
		// still in Twine for now
		let container = document.createElement("div");
		V.i = arcID;
		App.UI.DOM.includePassage(container, "Neighbor Description");
		return container;
	}

	/** Create a fragment containing all the details for a given arcology
	 * @param {number} arcID
	 * @returns {DocumentFragment}
	 */
	function details(arcID) {
		let frag = document.createDocumentFragment();
		if (arcID === 0) {
			const desc = FutureSocieties.activeFSes(0).map((f) => FutureSocieties.displayName(f));
			if (desc.length === 0) {
				App.UI.DOM.appendNewElement("p", frag, `Your arcology's culture has not developed to the point where it can meaningfully influence other arcologies.`);
			} else if (desc.length > 2) {
				App.UI.DOM.appendNewElement("p", frag, `Your arcology's mature culture is capable of exerting great cultural sway over other arcologies. It can readily project ${desc.reduce((res, ch, i, arr) => res + (i === arr.length - 1 ? ' and ' : ', ') + ch)}.`);
			} else if (desc.length === 2) {
				App.UI.DOM.appendNewElement("p", frag, `Your arcology's culture is capable of exerting some cultural sway over other arcologies. It can effectively project ${desc[0]} and ${desc[1]}.`);
			} else {
				App.UI.DOM.appendNewElement("p", frag, `Your arcology's culture is capable of starting to exert cultural sway over other arcologies. It can project ${desc[0]}.`);
			}
		} else {
			const ownershipCost = 500*Math.trunc(V.arcologies[arcID].prosperity*(1+(V.arcologies[arcID].demandFactor/100)));
			frag.append(`A 1% interest in this arcology is worth ${cashFormat(ownershipCost)}. `);
			if (V.arcologies[arcID].ownership + V.arcologies[arcID].PCminority + V.arcologies[arcID].minority < 100) {
				frag.append(`The transaction fee is ${cashFormat(10000)}.`);
			}

			if (V.arcologies[arcID].ownership + V.arcologies[arcID].PCminority + V.arcologies[arcID].minority < 100) {
				let links = [];
				links.push(App.UI.DOM.link("Buy", (f) => {
					cashX(forceNeg(ownershipCost), "war");
					cashX(-10000, "war");
					V.arcologies[arcID].PCminority += 1;
					V.arcologies[arcID].demandFactor += 2;
				}, [], "Neighbor Interact"));
				if (V.arcologies[arcID].ownership + V.arcologies[arcID].PCminority + V.arcologies[arcID].minority <= 90) {
					if (V.cash > ownershipCost*10) {
						const link = App.UI.DOM.link("10%", (f) => {
							cashX(forceNeg(ownershipCost*10), "war");
							cashX(-10000, "war");
							V.arcologies[arcID].PCminority += 10;
							V.arcologies[arcID].demandFactor += 20;
						}, [], "Neighbor Interact");
						links.push(link);
					}
				}
				const div = App.UI.DOM.appendNewElement("div", frag, App.UI.DOM.generateLinksStrip(links));
				if (links.length > 1) {
					App.UI.DOM.appendNewElement("span", div, "Transaction costs will only be paid once.", "detail");
				}
			}

			if (V.arcologies[arcID].PCminority > 0) {
				let links = [];
				links.push(App.UI.DOM.link("Sell", (f) => {
					cashX(ownershipCost, "war");
					V.arcologies[arcID].PCminority -= 1;
					V.arcologies[arcID].demandFactor -= 2;
					if (V.arcologies[arcID].government !== "your agent" && V.arcologies[arcID].government !== "your trustees" && V.arcologies[arcID].rival !== 1) {
						if (V.arcologies[arcID].ownership + V.arcologies[arcID].PCminority + V.arcologies[arcID].minority < 10) {
							V.arcologies[arcID].ownership += 10;
						}
					}
					arcChanged(arcID);
				}, [], "Neighbor Interact"));
				if (V.arcologies[arcID].PCminority >= 10) {
					links.push(App.UI.DOM.link("10%", (f) => {
						cashX((ownershipCost*10), "war");
						V.arcologies[arcID].PCminority -= 10;
						V.arcologies[arcID].demandFactor -= 20;
						if (V.arcologies[arcID].government !== "your agent" && V.arcologies[arcID].government !== "your trustees" && V.arcologies[arcID].rival !== 1) {
							if (V.arcologies[arcID].ownership + V.arcologies[arcID].PCminority + V.arcologies[arcID].minority < 10) {
								V.arcologies[arcID].ownership += 10;
							}
						}
					}, [], "Neighbor Interact"));
				}
				App.UI.DOM.appendNewElement("div", frag, App.UI.DOM.generateLinksStrip(links));
			}

			if (V.arcologies[arcID].direction !== V.arcologies[0].embargoTarget) {
				frag.append(document.createElement("br"));
				frag.append(App.UI.DOM.passageLink("Target them for economic warfare", "Neighbor Interact", () => V.arcologies[0].embargoTarget = V.arcologies[arcID].direction));
			}

			if (V.PC.skill.hacking > 0) {
				if (V.arcologies[arcID].direction !== V.arcologies[0].CyberEconomicTarget) {
					frag.append(document.createElement("br"));
					frag.append(App.UI.DOM.passageLink("Target them for cyber economic warfare", "Neighbor Interact", () => V.arcologies[0].CyberEconomicTarget = V.arcologies[arcID].direction));
				}
				if (V.arcologies[arcID].direction !== V.arcologies[0].CyberReputationTarget) {
					frag.append(document.createElement("br"));
					frag.append(App.UI.DOM.passageLink("Target their leadership for character assassination", "Neighbor Interact", () => V.arcologies[0].CyberReputationTarget = V.arcologies[arcID].direction));
				}
			}
			if (FutureSocieties.influenceSources(0).length > 0) {
				if (V.arcologies[arcID].direction !== V.arcologies[0].influenceTarget) {
					frag.append(document.createElement("br"));
					frag.append(App.UI.DOM.passageLink("Set as influence target", "Neighbor Interact", () => V.arcologies[0].influenceTarget = V.arcologies[arcID].direction));
				}
			}

			if (V.arcologies[arcID].government === "your trustees" || V.arcologies[arcID].government === "your agent") {
				frag.append(controlActions(arcID));
			}

			frag.append(fsGoods(arcID));
		}
		return frag;
	}

	/** Create a div containing actions specific to arcologies that are under the player's control
	 * @param {number} arcID
	 * @returns {Element}
	 */
	function controlActions(arcID) {
		const container = document.createElement("div");
		const agent = App.currentAgent(arcID);
		const him = agent ? getPronouns(agent).him : "them";
		container.append(document.createElement("br"));
		if (V.arcologies[arcID].government === "your trustees") {
			container.append(App.UI.DOM.passageLink("Appoint an agent", "Agent Select"));
		} else {
			let linkText = `Recall and reenslave ${him}`;
			const residentList = [agent.ID];
			const agentPartner = V.slaves.find((s) => s.assignment === Job.AGENTPARTNER && s.relationshipTarget === agent.ID);
			if (agentPartner) {
				linkText = `Recall them and reenslave your agent`;
				residentList.push(agentPartner.ID);
			}
			container.append(App.UI.SlaveList.render.listDOM(residentList, [], App.UI.SlaveList.SlaveInteract.stdInteract));
			container.append(App.UI.DOM.link(linkText, (f) => { removeJob(agent, "be your agent"); arcChanged(arcID); }));
		}
		container.append(" | ");
		const rename = App.UI.DOM.appendNewElement("span", container, '');
		rename.id = "rename";
		rename.append(App.UI.DOM.link(`Instruct ${him} to rename the arcology`, () => $("#rename").replaceWith([
			App.UI.DOM.makeTextBox(V.arcologies[arcID].name, (s) => { V.arcologies[arcID].name = s; }, false),
			App.UI.DOM.link("Confirm name", arcChanged, [arcID])
		])));

		if (V.arcologies[arcID].government === "your agent") {
			const {His, his, he, himself /* him is already set */} = getPronouns(agent);
			let r = [];
			r.push(`${His} ${agent.intelligence > 95 ? `brilliance` : `intelligence`} and education are the most important qualities for ${him}.`);
			if (agent.actualAge > 35) {
				r.push(`As with the Head Girl position, ${his} age and experience lend ${him} leadership weight.`);
			}
			if (agent.career === "an arcology owner") {
				r.push(`${His} career as an arcology owner ${himself} is, obviously, useful to ${him}.`);
			} else if (setup.HGCareers.includes(agent.career)) {
				r.push(`${His} career in leadership helps ${him}.`);
			}
			if (agent.fetishStrength > 95) {
				if ((agent.fetish === "dom") || (agent.fetish === "sadist")) {
					r.push(`${His} sexually dominant fetish helps ${him} fill a leadership role.`);
				} else if ((agent.fetish === "submissive") || (agent.fetish === "masochist")) {
					r.push(`Unfortunately, ${he} has an inappropriate fetish for a leader.`);
				} else {
					r.push(`${His} sexual fetishes will influence how ${he} leads the arcology.`);
				}
			}
			if (agent.energy > 95) {
				r.push(`Finally, ${his} sexual depravity lets ${him} fit into arcology society naturally.`);
			}
			App.UI.DOM.appendNewElement("div", container, r.join(' ' ));
		}

		container.append(document.createElement("br"));
		const forceAbandonment = (fs) => { V.arcologies[arcID][fs] = "unset"; arcChanged(arcID); };
		for (const fs of FutureSocieties.activeFSes(arcID)) {
			App.UI.DOM.appendNewElement("div", container, App.UI.DOM.link(`Force abandonment of ${FutureSocieties.displayName(fs)}`, forceAbandonment, [fs]));
		}

		return container;
	}

	/** Create an element containing all the society-dependent stuff you can buy from this arcology.
	 * @param {number} arcID
	 * @returns {Element}
	 */
	function fsGoods(arcID) {
		const container = document.createElement("div");
		let r = [];
		r.push(`If ${V.arcologies[arcID].name} has developed enough to begin exporting worthwhile goods, it may be of interest to acquire some.`);
		const opinionDiscount = App.Neighbor.opinion(arcID, 0)*10;
		const basePrice = Math.trunc((7500-opinionDiscount)*V.upgradeMultiplierTrade);
		const controlled = (V.arcologies[arcID].government === "your trustees") || (V.arcologies[arcID].government === "your agent");
		if (controlled) {
			r.push(`Since it is under your control, it is no problem at all to request the transfer of goods to ${V.arcologies[0].name}.`);
		} else if (V.PC.skill.hacking >= 50) {
			r.push(`It is within your skills to redirect an outgoing shipment to ${V.arcologies[0].name} for your retrieval.`);
		} else if (V.arcologies[arcID].direction === V.arcologies[0].embargoTarget) {
			r.push(`However, due to your active embargo, trade with ${V.arcologies[arcID].name} is not possible.`);
		}
		App.UI.DOM.appendNewElement("p", container, r.join(' '));

		let exports = 0;

		/** Build a link or text block describing how to acquire a specific good from this arcology
		 * @param {string} fsRequired - the FS that the arcology has to have for this block to appear
		 * @param {string} itemName - the item name to check to see if the player already has this item
		 * @param {string} category - the category to check to see if the player already has this item
		 * @param {string} itemDisplay - a display name for a group of the item; as in, "a shipment of XXX" or "enough XXX"
		 * @param {string} property - the global property controlling whether this item has been acquired
		 * @param {number} [itemPrice] - the price the player should pay for the item; by default, basePrice (computed above)
		 */
		function addAcquisitionBlock(fsRequired, itemName, category, itemDisplay, property, itemPrice = basePrice) {
			if (V.arcologies[arcID][fsRequired] > 95) {
				if (!isItemAccessible.entry(itemName, category)) {
					if (controlled) {
						const link = App.UI.DOM.link(`Request a shipment of ${itemDisplay}`, (f) => {
							V[property] = 1;
							replaceDetails(arcID);
						});
						App.UI.DOM.appendNewElement("div", container, link);
					} else if (V.PC.skill.hacking >= 50) {
						const link = App.UI.DOM.link(`Divert an outgoing shipment of ${itemDisplay}`, (f) => {
							V[property] = 1;
							replaceDetails(arcID);
						});
						App.UI.DOM.appendNewElement("div", container, link);
					} else if (V.arcologies[arcID].direction !== V.arcologies[0].embargoTarget) {
						const link = App.UI.DOM.link(`Divert an outgoing shipment of ${itemDisplay}`, (f) => {
							V[property] = 1;
							cashX(forceNeg(itemPrice), "capEx");
							// replaceDetails(arcID); - cash changed, force passage transition for sidebar update
						}, [], "Neighbor Interact");
						const div = App.UI.DOM.appendNewElement("div", container, link);
						App.UI.DOM.appendNewElement("span", div, `Will cost ${cashFormat(itemPrice)}`, "detail");
					}
				} else {
					App.UI.DOM.appendNewElement("div", container, `You already have enough ${itemDisplay}.`);
				}
				exports = 1;
			}
		}

		addAcquisitionBlock("FSRomanRevivalist", "a toga", "clothing", "togas", "clothesBoughtToga");
		addAcquisitionBlock("FSEdoRevivalist", "a kimono", "clothing", "kimonos", "clothesBoughtKimono");
		addAcquisitionBlock("FSArabianRevivalist", "harem gauze", "clothing", "silken harem garb", "clothesBoughtHarem");
		addAcquisitionBlock("FSAztecRevivalist", "a huipil", "clothing", "huipils", "clothesBoughtHuipil");
		addAcquisitionBlock("FSChineseRevivalist", "a slutty qipao", "clothing", "skimpy qipaos", "clothesBoughtQipao");
		addAcquisitionBlock("FSEgyptianRevivalist", "ancient Egyptian", "collar", "Egyptian necklace replicas", "clothesBoughtEgypt");
		addAcquisitionBlock("FSPaternalist", "conservative clothing", "clothing", "conservative clothing", "clothesBoughtConservative");
		addAcquisitionBlock("FSDegradationist", "chains", "clothing", "binding chains", "clothesBoughtChains");
		addAcquisitionBlock("FSGenderFundamentalist", "a bunny outfit", "clothing", "bunny suits", "clothesBoughtBunny");
		addAcquisitionBlock("FSIntellectualDependency", "a bimbo outfit", "cloting", "bimbo attire", "clothesBoughtBimbo");
		addAcquisitionBlock("FSSlaveProfessionalism", "a courtesan dress", "clothing", "cortesan dresses", "clothesBoughtCourtesan");
		// addAcquisitionBlock("FSPetiteAdmiration", "petite dress", "clothing", "petite-sized dresses", "clothesBoughtPetite");
		addAcquisitionBlock("FSPhysicalIdealist", "body oil", "clothing", "body oil", "clothesBoughtOil");
		addAcquisitionBlock("FSHedonisticDecadence", "stretch pants and a crop-top", "clothing", "stretch pants and crop-tops", "clothesBoughtLazyClothes");
		addAcquisitionBlock("FSChattelReligionist", "a chattel habit", "clothing", "chattel religionist habits", "clothesBoughtHabit");
		addAcquisitionBlock("FSPastoralist", "Western clothing", "clothing", "Western clothing", "clothesBoughtWestern");
		addAcquisitionBlock("FSRepopulationFocus", "a maternity dress", "clothing", "maternity dresses", "clothesBoughtMaternityDress");
		addAcquisitionBlock("FSRepopulationFocus", "attractive lingerie for a pregnant woman", "clothing", "maternity lingerie", "clothesBoughtMaternityLingerie");
		addAcquisitionBlock("FSRepopulationFocus", "a small empathy belly", "bellyAccessory", "empathy bellies", "clothesBoughtBelly");
		addAcquisitionBlock("FSStatuesqueGlorification", "platform heels", "shoes", "platform shoes", "shoesBoughtHeels");

		if (exports !== 1) {
			const luck = (V.arcologies[arcID].direction === V.arcologies[0].embargoTarget) ? `Fortunately` : `Unfortunately`;
			App.UI.DOM.appendNewElement("p", container, `${luck}, they have nothing of value.`);
		}

		return container;
	}

	return list;
})();

src/neighbor/neighborInteract.js