// TODO: beer nuts
// TODO: after-nightcap drunki-bears
// TODO: milk of magnesium
// TODO: fudge spork
// TODO: distention pill value
// TODO: be more adventurous. chocolate-like, 2 advs per, up to 5

function indices(xs) {
	var is = {}
	for (var x in xs) {
		is[x] = true
	}
	return is
}

function item_sortkey(c, extra, is_nightcap) {
	if (c["type"] == "modifier") return 0
	else if (c["type"] == "organ size") return 1
	else if (c["type"] == "used item" && c["name"] == "chocolate {class starting weapon}") return 10
	else if (c["type"] == "used item") return 2
	else if (c["type"] == "fortune cookie") return 1000
	else if (c["type"] == "food") return 1010
	else if (c["type"] == "booze" && !is_nightcap) return 2000
	else if (c["type"] == "booze" && is_nightcap) return 3000
	else if (c["type"] == "spleen") return 4000
	else return -1000
}

function desc_number(n) {
	if (n < 0) return "-" + desc_number(-n)
	if (n > 3000000000) return (n / 1000000000.0).toFixed(1) + "G"
	else if (n > 3000000) return (n / 1000000.0).toFixed(1) + "M"
	else if (n > 3000) return (n / 1000.0).toFixed(1) + "k"
	else if (Math.floor(n) == n) return n.toFixed(0)
	else return n.toFixed(1)
}

function desc_plural(base, plural, amount) {
	if (amount == 1) {
		return "1 " + base
	} else {
		return desc_number(amount) + " " + plural
	}
}

function desc_item(x) {
	var c = x.raw_x.raw_c
// 	var price = desc_number(x.raw_x.price)
	var price = x.raw_x.price.toFixed(0)
	var turns = ""
	if (x.override_turns) {
// 		console.log("override for", c, x)
		turns = x.override_turns.toFixed(0)
	} else if (x.raw_x.turns == 0) {
	} else {
		turns = (x.raw_x.turns * x.amount).toFixed(0)
	}
	var specialprice = ""
	if (c["specialprice"]) {
		specialprice = " (" + c["specialprice"] + ")"
	}
	var usemod = ""
	if (x.is_nightcap) {
		usemod = " (nightcap)"
	} else if (c["name"] == "milk of magnesium") {
		usemod = " (always assumed)"
	}
// 	return x.amount + "x " + "<a href=\"http://kol.coldfront.net/thekolwiki/index.php/Special:Search?search=" + c["name"] + "\">" + c["name"] + "</a>" + x.raw_x.extra + " [" + price + " meat" + specialprice + turnstext + "]" + usemod
	var ret = {}
	ret["amount"] = x.amount
	ret["name"] = c["name"]
	ret["extra"] = x.raw_x.extra
	ret["price"] = price
	ret["turns"] = turns
	ret["notes"] = specialprice + " " + usemod
	ret["idx"] = c["idx"]
	return ret
}

function calc_advs_raw(c, mod, num_milk_of_magnesia, with_field_gar, tuxedo_available) {
	var advs_sum = 0.0
	var advs_num = 0.0
	for (var base_a = c["advmin"]; base_a <= c["advmax"]; ++base_a) {
		var a = base_a
		if (mod == "munchies" || mod == "munchies+fork") {
			if (a <= 3) {
				a += 3
			} else if (a <= 6) {
				a += 2
			} else {
				a += 1
			}
		}
		if (mod == "fork" || mod == "munchies+fork") {
			if (c["item class"] == "salad") {
				a = Math.ceil(a * 1.5)
			} else {
				a = Math.ceil(a * 1.3)
			}
		} else if (mod == "mug") {
			if (c["item class"] == "beer") {
				a = Math.floor(a * 1.5)
			} else {
				a = Math.floor(a * 1.3)
			}
		}
		if (c["type"] == "booze") {
			a += c["size"][1] // ode
		}
		if (c["type"] == "food" && num_milk_of_magnesia >= 1) { // TODO: do better!
			a += c["size"][0] // milk of magnesium
		}
		if (c["item class"] == "lasagna" && with_field_gar) {
			a += 5
		}
		if (c["tuxedo boostable drink"] == "yes" && tuxedo_available) {
			a += 2
		}
		advs_sum += a
		advs_num += 1.0
	}
	return advs_sum / advs_num
}

function compute_diet(diet_settings) {
	var adv_value = diet_settings["adventure value"]
	var start_organs = diet_settings["organ sizes"]
	var item_prices = {}
	var food_items = []
	var booze_items = []
	var spleen_items = []
	var fortune_cookie_items = []
	var item_data = diet_settings["item data"]
	var excluded = diet_settings["excluded consumables"]
	var with_field_gar = (diet_settings["use potion of the field gar"] == "yes")
	var num_milk_of_magnesia = 1
	var tps_available = diet_settings["tiny plastic sword available"]
	var tuxedo_available = diet_settings["tuxedo shirt available"]
	var semirares_available = diet_settings["semirares available"]
	var idx_lookup = {}
	for (var i_ in item_data) {
		if (excluded[i_]) continue
		var i = item_data[i_]
		i["idx"] = i_
		var name = i["name"]
		idx_lookup[name] = i_
		item_prices[name] = i["price"]
		if (tps_available && i["tpsprice"] && i["tpsprice"] < i["price"]) item_prices[name] = i["tpsprice"]
		if (i["type"] == "food") food_items.push(i)
		if (i["type"] == "booze") booze_items.push(i)
		if (i["type"] == "spleen") spleen_items.push(i)
		if (name == "fortune cookie") fortune_cookie_items.push(i)
	}
// 	var gotmilkturns = diet_settings["turns of got milk"]
	var include_nightcap = diet_settings["include nightcap"]

	function mk_modifier_item_thing(name, size, type) {
		var price = item_prices[name]
		var c = {
			size: size,
			value: -price,
			raw_c: {
				"name": name,
				"advmin": 0,
				"advmax": 0,
				"price": price,
				"type": type,
				"size": size
			},
			extra: "",
			turns: 0,
			price: price
		}
		if (name in idx_lookup && item_data[idx_lookup[name]]["specialprice"]) {
			c.raw_c["specialprice"] = item_data[idx_lookup[name]]["specialprice"]
		}
		return c
	}

	var start_value = 0
	var start_items = []
	if (with_field_gar) {
		start_value -= item_prices["potion of the field gar"]
		start_items.push({ raw_x: mk_modifier_item_thing("potion of the field gar", [0, 0, 0], "modifier"), amount: 1, is_nightcap: false })
	}
	if (num_milk_of_magnesia > 0) {
		start_value -= item_prices["milk of magnesium"]
		start_items.push({ raw_x: mk_modifier_item_thing("milk of magnesium", [0, 0, 0], "modifier"), amount: num_milk_of_magnesia, is_nightcap: false })
	}
	function maybe_add_start_item(opts) {
		var best_v = 0
		var best_push = []
		for (o_i in opts) {
			var o = opts[o_i]
			var v = 0
			for (x_i in o) {
				var x = o[x_i]
				v += adv_value * x[0]
				v -= item_prices[x[1]] * x[2]
			}
			if (v > best_v) {
				best_v = v
				best_push = o
			}
		}
		if (best_v > 0) {
			start_value += v
			for (x_i in best_push) {
				var x = best_push[x_i]
				start_items.push({ raw_x: mk_modifier_item_thing(x[1], [0, 0, 0], "used item"), amount: x[2], is_nightcap: false, override_turns: x[0] })
			}
		}
	}
	maybe_add_start_item([[[5, "time's arrow", 1]]])
	maybe_add_start_item([[[5, "essential tofu", 1]]])
	maybe_add_start_item([
		[[5, "vitachoconutriment capsule", 1]],
		[[5+3, "vitachoconutriment capsule", 2]],
		[[5+3+1, "vitachoconutriment capsule", 3]],
	])
	maybe_add_start_item([
		[[5, "chocolate cigar", 1]],
		[[5+3, "chocolate cigar", 2]],
		[[5+3+1, "chocolate cigar", 3]],
	])
	maybe_add_start_item([
		[[3, "chocolate {class starting weapon}", 1]],
		[[3+2, "chocolate {class starting weapon}", 2]],
		[[3+2+1, "chocolate {class starting weapon}", 3]],

		[[5, "fancy chocolate", 1]],
		[[5, "fancy chocolate", 1], [2, "chocolate {class starting weapon}", 1]],
		[[5, "fancy chocolate", 1], [2+1, "chocolate {class starting weapon}", 2]],
		[[5+3, "fancy chocolate", 2]],
		[[5+3, "fancy chocolate", 2], [1, "chocolate {class starting weapon}", 1]],
		[[5+3+1, "fancy chocolate", 3]],

		[[5, "fancy but probably evil chocolate", 1]],
		[[5, "fancy but probably evil chocolate", 1], [2, "chocolate {class starting weapon}", 1]],
		[[5, "fancy but probably evil chocolate", 1], [2+1, "chocolate {class starting weapon}", 2]],
		[[5+3, "fancy but probably evil chocolate", 2]],
		[[5+3, "fancy but probably evil chocolate", 2], [1, "chocolate {class starting weapon}", 1]],
		[[5+3+1, "fancy but probably evil chocolate", 3]],

		[[5, "fancy chocolate car", 1]],
		[[5, "fancy chocolate car", 1], [2, "chocolate {class starting weapon}", 1]],
		[[5, "fancy chocolate car", 1], [2+1, "chocolate {class starting weapon}", 2]],
		[[5+3, "fancy chocolate car", 2]],
		[[5+3, "fancy chocolate car", 2], [1, "chocolate {class starting weapon}", 1]],
		[[5+3+1, "fancy chocolate car", 3]],
	])
	var best = {}
	best[start_organs] = { organs: start_organs, value: start_value, items: start_items }

	function calc_advs(c, mod) {
		return calc_advs_raw(c, mod, num_milk_of_magnesia, with_field_gar, tuxedo_available)
	}
	function reduce_consumables(xs_all, blank_item_size) {
		var xs = []
		var best_xs = {}
		best_xs[blank_item_size] = 0.0
		xs.push({ size: blank_item_size, value: 0.0, raw_c: { "name": "blank item", "advmin": 0, "advmax": 0, "price": 0, "type": "blank item", "size": blank_item_size }, extra: "", turns: 0, price: 0})
		function maybe_add(turns, price, c, extra) {
			var v = turns * adv_value - price
			var s = c["size"]
			if (best_xs[s] && c["name"]) {
				if (best_xs[s] >= v - 0.00001) {
					return
				}
			}
			best_xs[s] = v
			xs.push({ size: s, value: v, raw_c: c, extra: extra, turns: turns, price: price })
		}
		for (var x in xs_all) {
			var c = xs_all[x]
			maybe_add(calc_advs(c, ""), item_prices[c["name"]], c, "")
			if (c["type"] == "food") {
				maybe_add(calc_advs(c, "munchies"), item_prices[c["name"]] + item_prices["munchies pill"], c, " (with munchies pill)")
				maybe_add(calc_advs(c, "fork"), item_prices[c["name"]] + item_prices["Ol' Scratch's salad fork"], c, " (with salad fork)")
				maybe_add(calc_advs(c, "munchies+fork"), item_prices[c["name"]] + item_prices["munchies pill"] + item_prices["Ol' Scratch's salad fork"], c, " (with munchies pill and salad fork)")
			}
			if (c["type"] == "booze") {
				maybe_add(calc_advs(c, "mug"), item_prices[c["name"]] + item_prices["Frosty's frosty mug"], c, " (with frosty mug)")
			}
		}
		return xs
	}
	function add_item(newbest, new_size, new_value, prev_items, amount, x, is_nightcap) {
		if (new_size[0] < 0) return false
		if (new_size[1] < 0) return false
		if (new_size[2] < 0) return false
		if (new_size in newbest) {
			if (new_value <= newbest[new_size].value + 0.00001) {
				return true
			}
		}
		newbest[new_size] = { organs: new_size, value: new_value, items: prev_items.concat([{ raw_x: x, amount: amount, is_nightcap: is_nightcap }]) }
		return true
	}
	function run_it(xs_all, keepfilter, blank_item_size) {
		var xs = reduce_consumables(xs_all, blank_item_size)
		var newbest = {}
		for (var b_i in best) {
			newbest[b_i] = best[b_i]
		}
		oldbest = best
		best = newbest
		for (var c_i in xs) {
			var c = xs[c_i]
			for (var b_i in indices(best)) {
				var old_size = best[b_i].organs
				for (var times = 1; times <= 1000; times += 1) {
					var new_size = [old_size[0] - c["size"][0] * times, old_size[1] - c["size"][1] * times, old_size[2] - c["size"][2] * times]
					var new_value = best[b_i].value + c.value * times
					if (!add_item(best, new_size, new_value, best[b_i].items, times, c, false)) break
				}
			}
		}
		var newbest = {}
		for (var b_i in best) {
			if (keepfilter(b_i)) {
				newbest[b_i] = best[b_i]
			}
		}
		best = newbest
	}
	function run_nightcap(xs_all, keepfilter, blank_item_size) {
		var xs = reduce_consumables(xs_all, blank_item_size)
		var newbest = {}
		for (var b_i in indices(best)) {
			newbest[b_i] = best[b_i]
		}
		for (var c_i in xs) {
			var c = xs[c_i]
			for (var b_i in indices(best)) {
				var old_size = best[b_i].organs
				var new_size = [old_size[0] - c["size"][0], old_size[1], old_size[2] - c["size"][2]]
				var new_value = best[b_i].value + c.value
				add_item(newbest, new_size, new_value, best[b_i].items, 1, c, true)
			}
		}
		best = newbest
	}

	var oldbest = {}
	for (var b_i in best) {
		oldbest[b_i] = best[b_i]
	}
	for (var b_i in oldbest) {
		var old_size = oldbest[b_i].organs
		var new_size = [old_size[0] + 3, old_size[1] + 3, old_size[2]]
		var new_value = oldbest[b_i].value - item_prices["spice melange"]
		add_item(best, new_size, new_value, oldbest[b_i].items, 1, mk_modifier_item_thing("spice melange", [-3, -3, 0], "organ size"), false)
	}

	var oldbest = {}
	for (var b_i in best) {
		oldbest[b_i] = best[b_i]
	}
	for (var b_i in oldbest) {
		var xs = reduce_consumables(fortune_cookie_items, [1, 0, 0])
		for (var c_i in xs) {
			var c = xs[c_i]
			if (c.raw_c["name"] != "fortune cookie") continue
			for (var times = 1; times <= semirares_available; times += 1) {
				var old_size = oldbest[b_i].organs
				var new_size = [old_size[0] - c["size"][0] * times, old_size[1] - c["size"][1] * times, old_size[2] - c["size"][2] * times]
				var new_value = oldbest[b_i].value + (c.value + 11000 - adv_value * 1.25) * times // rough estimate: 11k for semirare, 1.25 turns to pick it up
				add_item(best, new_size, new_value, oldbest[b_i].items, times, c, false)
			}
		}
	}

	run_it(food_items, function(x) {
		return best[x].organs[0] == 0
	}, [1, 0, 0])
	run_it(booze_items, function(x) {
		return (best[x].organs[1] == 0)
	}, [0, 1, 0])
	if (include_nightcap == "yes") {
		run_nightcap(booze_items, function(x) {
			return true
		}, [0, 1, 0])
	}

	oldbest = {}
	for (var b_i in best) {
		oldbest[b_i] = best[b_i]
	}
	for (var b_i in oldbest) {
		for (var times = 1; times <= 3; times += 1) {
			var old_size = oldbest[b_i].organs
			var new_size = [old_size[0], old_size[1], old_size[2] + times]
			var new_value = oldbest[b_i].value - item_prices["mojo filter"] * times
			add_item(best, new_size, new_value, oldbest[b_i].items, times, mk_modifier_item_thing("mojo filter", [0, 0, -1], "organ size"), false)
		}
	}

	run_it(spleen_items, function(x) {
		return (best[x].organs[2] == 0)
	}, [0, 0, 1])
	var ixs = best[[0, 0, 0]].items
	var diet_items = []
	for (var x_i in ixs) {
		var x = ixs[x_i]
		var turns = x.raw_x.turns * x.amount
		if (x.override_turns) {
			turns = x.override_turns
		}
		diet_items.push({ desc: desc_item(x), sortkey: item_sortkey(x.raw_x.raw_c, x.raw_x.extra, x.is_nightcap), name: x.raw_x.raw_c.name, turns: turns, price: x.raw_x.price * x.amount, value: x.raw_x.value * x.amount })
	}
	diet_items.sort(function (a, b) {
		if (a.sortkey < b.sortkey) return -1
		if (a.sortkey > b.sortkey) return 1
		return a.name.localeCompare(b.name)
	})
	return diet_items
}

