'''share all plans in an account and generate a CSV of the construction materials'''

from __future__ import annotations
import collections
import csv
import math
import sys
import typing

import httpx

import cache

def main():
	jwt,= sys.argv[1:]

	with httpx.Client(headers={'Authorization': 'Bearer ' + jwt}) as client:
		plans: typing.Sequence[Plan] = client.get('https://api.prunplanner.org/baseplanner/').raise_for_status().json()
		shared: typing.Mapping[str, str] = {s['plan_uuid']: s['shared_uuid']
				for s in client.get('https://api.prunplanner.org/shared/list').raise_for_status().json()}
		for plan in plans:
			if plan['uuid'] not in shared:
				print('sharing', plan['uuid'], plan['name'])
				client.put('https://api.prunplanner.org/shared/baseplanner/' + plan['uuid']).raise_for_status()
		# refresh shared UUIDs
		shared: typing.Mapping[str, str] = {s['plan_uuid']: s['shared_uuid']
				for s in client.get('https://api.prunplanner.org/shared/list').raise_for_status().json()}

	buildings: typing.Mapping[str, BuildingData] = {b['Ticker']: b for b in cache.get('https://api.prunplanner.org/data/buildings')}

	writer = csv.DictWriter(sys.stdout, fieldnames=['plan', 'share', 'PSL', 'TRU', 'MCG', 'BL', 'MGC', 'HSE', 'SEA', 'INS', 'TSH', 'BBH', 'BDE', 'BSE', 'BTA', 'LBH', 'LDE', 'LSE', 'LTA', 'RBH', 'RDE', 'RSE', 'RTA', 'ABH', 'ADE', 'ASE', 'ATA'])
	writer.writeheader()
	for plan in plans:
		shared_uuid = shared[plan['uuid']]

		planet: Planet = cache.get('https://api.prunplanner.org/data/planet/' + plan['baseplanner_data']['planet']['planetid'])
		plan_mats = collections.defaultdict(int)
		for mat in mats(buildings['CM'], planet):
			plan_mats[mat['CommodityTicker']] += mat['Amount']
		for plan_building in plan['baseplanner_data']['buildings']:
			building_data = buildings[plan_building['name']]
			for mat in mats(building_data, planet):
				plan_mats[mat['CommodityTicker']] += mat['Amount'] * plan_building['amount']
		for infra_building in plan['baseplanner_data']['infrastructure']:
			building_data = buildings[infra_building['building']]
			for mat in mats(building_data, planet):
				plan_mats[mat['CommodityTicker']] += mat['Amount'] * infra_building['amount']
		writer.writerow({'plan': plan['name'], 'share': 'https://prunplanner.org/shared/' + shared_uuid, **plan_mats})

def mats(building: BuildingData, planet: Planet) -> typing.Iterator[BuildingMat]:
	for mat in building['BuildingCosts']:
		yield mat

	if planet['Surface']:  # rocky
		yield {'CommodityTicker': 'MCG', 'Amount': building['AreaCost'] * 4}
	else:  # gaseous
		yield {'CommodityTicker': 'AEF', 'Amount': math.ceil(building['AreaCost'] / 3)}

	if planet['Gravity'] > 2.5:
		yield {'CommodityTicker': 'BL', 'Amount': 1}
	elif planet['Gravity'] < 0.25:
		yield {'CommodityTicker': 'MGC', 'Amount': 1}

	if planet['Pressure'] > 2:
		yield {'CommodityTicker': 'HSE', 'Amount': 1}
	elif planet['Pressure'] < 0.25:
		yield {'CommodityTicker': 'SEA', 'Amount': building['AreaCost']}

	if planet['Temperature'] < -25:
		yield {'CommodityTicker': 'INS', 'Amount': building['AreaCost'] * 10}
	elif planet['Temperature'] > 75:
		yield {'CommodityTicker': 'TSH', 'Amount': 1}

class Plan(typing.TypedDict):
	uuid: str
	name: str
	baseplanner_data: BaseplannerData

class BaseplannerData(typing.TypedDict):
	planet: dict
	infrastructure: typing.Sequence[InfrastructureBuilding]
	buildings: typing.Sequence[PlanBuilding]

class InfrastructureBuilding(typing.TypedDict):
	building: str
	amount: int

class PlanBuilding(typing.TypedDict):
	name: str
	amount: int

class Planet(typing.TypedDict):
	Surface: bool
	Pressure: float
	Temperature: float
	Gravity: float

class BuildingData(typing.TypedDict):
	Ticker: str
	AreaCost: int
	BuildingCosts: list[BuildingMat]

class BuildingMat(typing.TypedDict):
	CommodityTicker: str
	Amount: int

if __name__ == '__main__':
	main()
