<script>
import Euro from "util/Euro.svelte";
import ProgressBar from "util/ProgressBar.svelte";

let nova_storage = $state(0)
let nova_egress = $state(0)
let nova_total = $state(0)
let backblaze_storage = $state(0)
let backblaze_egress = $state(0)
let backblaze_api = $state(0)
let backblaze_total = $state(0)
let wasabi_storage = $state(0)
let wasabi_total = $state(0)
let price_max = $state(0)

let storage = $state(10) // TB
let egress = $state(10) // TB
let avg_file_size = $state(1000) // kB

$effect(() => {
	// Nova has a minimum file size of 10kB. Calculate the number of files from
	// storage and avg file size, then calculate storage usage based on that.
	nova_storage = Math.max(storage * 4, ((storage*10)/avg_file_size)*4)
	nova_egress = egress * 1
	nova_total = nova_storage + nova_egress

	// Egress at Backblaze is free up to three times the amount of storage, then
	// it's $10/TB
	backblaze_storage = storage * 6
	backblaze_egress = Math.max(egress - (storage * 3), 0) * 10
	backblaze_api = ((egress * 1e12) / (avg_file_size * 1e3)) * 0.0000004
	backblaze_total = backblaze_storage + backblaze_egress + backblaze_api

	// Wasabi does not have egress fees
	wasabi_storage = storage * 6.99
	wasabi_total = (egress > storage) ? 0 : wasabi_storage

	price_max = Math.max(nova_total, backblaze_total, wasabi_total)
});
</script>

<h2>Price calculator</h2>
<div class="inputs">
	<div>
		<div class="usage_label">Storage</div>
		<div class="usage_input">
			<input type="number" bind:value={storage}/>
			<div>TB / month</div>
		</div>
	</div>
	<div>
		<div class="usage_label">Egress</div>
		<div class="usage_input">
			<input type="number" bind:value={egress}/>
			<div>TB / month</div>
		</div>
	</div>
	<div>
		<div class="usage_label">Average file size</div>
		<div class="usage_input">
			<input type="number" bind:value={avg_file_size}/>
			<div>kB</div>
		</div>
	</div>
</div>

<div class="bars">
	<div>
		<div>
			Nova.storage - <Euro amount={nova_total*1e6}/> / month<br/>
			<Euro amount={nova_storage*1e6}/> storage,
			<Euro amount={nova_egress*1e6}/> egress
			<ProgressBar used={nova_total} total={price_max}/>
		</div>
		{#if avg_file_size < 10}
			<div>
				Nova counts a minimum file size of 10 kB. Files smaller than that
				are rounded up to 10 kB.
			</div>
		{/if}
	</div>
	<div>
		<div>
			Backblaze B2 - <Euro symbol="$" amount={backblaze_total*1e6}/> / month<br/>
			<Euro symbol="$" amount={backblaze_storage*1e6}/> storage,
			<Euro symbol="$" amount={backblaze_egress*1e6}/> egress,
			<Euro symbol="$" amount={backblaze_api*1e6}/> API calls
			<ProgressBar used={backblaze_total} total={price_max}/>
		</div>
	</div>
	<div>
		<div>
			Wasabi - <Euro symbol="$" amount={wasabi_total*1e6}/> / month<br/>
			<Euro symbol="$" amount={wasabi_storage*1e6}/> storage
			<ProgressBar used={wasabi_total} total={price_max}/>
		</div>
		{#if egress > storage}
			<div>
				Wasabi does not allow users to download more than their amount
				of stored data per month. For this reason Wasabi is excluded
				from price calculations when egress is higher than storage.
			</div>
		{/if}
	</div>
</div>

<p>
	Note that while Nova.storage might not seem to be the cheapest option in some
	cases, most cloud providers have extra hidden costs for API calls and
	region-specific prices. This makes it very hard to accurately compare the
	pricing of these platforms. Nova.storage includes no hidden costs, I only
	charge for storage and egress.
</p>
<p>
	Large cloud providers like Amazon, Microsoft and Google are excluded from
	this calculation because their pricing is too complex accurately compare
	them. Just assume that Nova wil be cheaper.
</p>

<style>
.inputs {
	display: flex;
	flex-direction: row;
	justify-content: center;
	gap: 10px;
	margin-bottom: 10px;
}
@media(max-width: 700px) {
	.inputs {
		flex-direction: column;
	}
}
.inputs > div {
	flex: 1 1 100%;
	display: flex;
	flex-direction: column;
	border-radius: 6px;
	overflow: hidden;
	border: 2px solid var(--card_color);
}
.usage_label {
	flex: 1 1 auto;
	text-align: center;
	font-size: 1.3em;
	padding: 4px;
}
.usage_input {
	flex: 1 1 auto;
	background: var(--card_color);
	display: flex;
	flex-direction: row;
	align-items: center;
}
.usage_input > input {
	flex: 1 1 auto;
	background: var(--card_color);
}
.usage_input > div {
	flex: 0 0 auto;
	background: var(--card_color);
}
.bars {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 10px;
}
.bars > div {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	border-radius: 6px;
	overflow: hidden;
	border: 2px solid var(--card_color);
}
.bars > div > div {
	padding: 4px;
}
.bars > div > div:first-child {
	background: var(--card_color);
}
</style>
