WALLETS = [
	'boot',
	'brave',
	'metamask',
];

provider_rpc_url = 'http://localhost:8545';
wallet_fallback = undefined;
wallet_init = false;
wallet_registered = {};
provider_registered = {};
var current_provider = null;
var current_signer = null;
ethers = undefined;

function register_ethers(m) {
	ethers = m;
}

function wallet_register(wallet_key, wallet_constructor) {
	if (!wallet_key in WALLETS) {
		throw 'unknown wallet: ' + wallet;
	}
	if (wallet_registered[wallet_key] != undefined) {
		console.warn('wallet already registered', wallet_key);
		return;
	}
	console.log('registered wallet', wallet_key);
	wallet_registered[wallet_key] = wallet_constructor;
}

function provider_register(provider_key, provider_constructor) {
	if (provider_registered[provider_key] != undefined) {
		console.warn('provider already registered', provider_key);
		return;
	}
	console.log('registered provider', provider_key);
	provider_registered[provider_key] = provider_constructor;
}

async function wallet_connect(wallet_key, instanceId, passphrase) {
	if (!passphrase) {
		passphrase = undefined;
	}
	const fn = wallet_registered[wallet_key];
	let signer = await fn(instanceId, passphrase);
	let signed_connected;
	try {
		signer_connected = await signer.connect(current_provider);
	} catch(e) {
		console.debug('signer connect error', e);
		signer_connected = await current_provider.getSigner();
	}
	current_signer = signer_connected;
	console.log('connected to wallet', wallet_key, current_signer);
	return current_signer;
}

async function provider_connect(provider_key) {
	const fn = provider_registered[provider_key];
	current_provider = await fn();
	console.log('registered provider', provider_key);
	return current_provider;
}

function wallet_detect(ethers_instance) {
	if (wallet_init) {
		return;
	}
	ethers = ethers_instance;
	if (wallet_fallback !== undefined) {
		wallet_register('default', wallet_fallback);
	}	
	if (window.ethereum != null) {
		if (window.ethereum.isBraveWallet) {
			wallet_register('brave', metamaskish_signer_connect);
			provider_register('brave', metamaskish_provider_connect);
		} else if (window.ethereum.isMetaMask) {
			wallet_register('metamask', metamaskish_signer_connect);
			provider_register('metamask', metamaskish_provider_connect);
		}
	}
	wallet_init = true;
}

async function metamaskish_provider_connect() {
	let provider;
	return new ethers.BrowserProvider(window.ethereum)
}

async function metamaskish_signer_connect() {
	let signer_provider;
	if (current_provider != null) {
		signer_provider = current_provider;
	} else {
		current_provider = new ethers.BrowserProvider(window.ethereum);
		signer_provider = current_provider;
	}
	return await signer_provider.getSigner();
}

async function jsonrpc_provider_connect(url) {
	if (url === undefined) {
		url = provider_rpc_url;
	}
	return new ethers.JsonRpcProvider(url);
}

function getWallet(id) {
	return wallet_registered[id];
}

provider_register('default', jsonrpc_provider_connect);

function getProvider(id) {
	return provider_registered[id];
}