export class API {
	// query resolves into the JSON data produced by the application, or an exception with 'type' and 'error' properties.
	static async query(method, path, request) {
		return new Promise((resolve, reject) => {
			const body = JSON.stringify(request)
			const headers = {}

			// Authentication is done with a bearer token.
			// Here provided to the backend if set.
			const token = localStorage.getItem('token')
			if (token) {
				headers.Authorization = `Bearer ${token}`
			}

			fetch(path, { method, headers, body })
				.then(response => {
					// An HTTP communication level error occured.
					if (!response.ok || response.status != 200)
						return reject({
							type: 'http',
							error: response,
						})
					return response.json()
				})
				.then(json => {
					// Application level response are handled here.
					if (!json.OK)
						return reject({
							type: 'application',
							error: json.Error,
							application: json,
						})
					resolve(json)
				})
				.catch(err =>
					// Catch any other errors from fetch.
					reject({
						type: 'http',
						error: err,
					}))
		})
	}

	static hasAuthenticationToken() {//{{{
		const token = localStorage.getItem('token')
		return token !== null && token !== ''
	}//}}}
	static authenticate(username, password) {//{{{
		return new Promise((resolve, reject) => {
			const req = { username, password }
			API.query('POST', '/user/authenticate', req)
				.then(response => {
					localStorage.setItem('token', response.Token)
					localStorage.setItem('user', JSON.stringify(response.User))
					resolve(response.User)
				})
				.catch(e => {
					console.log(e.type, e.error)
					reject(e.error)
				})
		})
	}//}}}
	static logout() {//{{{
		localStorage.removeItem('token')
		location.href = '/'
	}//}}}
}
