'use strict'

const { send, json, createError } = require('micro')
const normalizeUrl = require('normalize-url')

const identifier = require('../utils/identifier')
const messages = require('../utils/messages')
const domains = require('../database/domains')
const records = require('../database/records')

const response = (entry) => ({
	type: 'record',
	data: {
		id: entry.id,
		domainId: entry.domainId,
		siteLocation: entry.siteLocation,
		siteReferrer: entry.siteReferrer,
		siteLanguage: entry.siteLanguage,
		screenWidth: entry.screenWidth,
		screenHeight: entry.screenHeight,
		screenColorDepth: entry.screenColorDepth,
		deviceName: entry.deviceName,
		deviceManufacturer: entry.deviceManufacturer,
		osName: entry.osName,
		osVersion: entry.osVersion,
		browserName: entry.browserName,
		browserVersion: entry.browserVersion,
		browserWidth: entry.browserWidth,
		browserHeight: entry.browserHeight,
		created: entry.created,
		updated: entry.updated
	}
})

const add = async (req, res) => {

	const { domainId } = req.params
	const clientId = identifier(req, domainId)
	const data = { ...await json(req), clientId, domainId }

	const domain = await domains.get(domainId)

	if (domain == null) throw createError(404, 'Unknown domain')

	if (data.siteLocation == null) {

		// Pre-validate siteLocation and imitate MongoDB error
		throw createError(400, `Path \`siteLocation\` is required`)

	}

	try {

		data.siteLocation = normalizeUrl(data.siteLocation)

	} catch (err) {

		throw createError(400, `Failed to normalize \`siteLocation\``, err)

	}

	let entry

	try {

		entry = await records.add(data)

	} catch (err) {

		if (err.name === 'ValidationError') {
			throw createError(400, messages(err.errors), err)
		}

		throw err

	}

	// Anonymize old entries with the same clientId to prevent that the browsing history
	// of a user is reconstructible. Will be skipped when there're no previous entries.
	await records.anonymize(clientId, entry.id)

	return send(res, 201, response(entry))

}

const update = async (req) => {

	const { recordId } = req.params

	let entry

	try {

		entry = await records.update(recordId)

	} catch (err) {

		if (err.name === 'ValidationError') {
			throw createError(400, messages(err.errors), err)
		}

		throw err

	}

	if (entry == null) throw createError(404, 'Unknown record')

	return response(entry)

}

module.exports = {
	add,
	update
}
@@ -971,290 +971,58 @@
 nst 
-add = async (req, res) =%3E %7B%0A%0A%09const %7B domainId %7D = req.params%0A%09const clientId = identifier(req, domainId)%0A%09const data = %7B ...await json(req), clientId, domainId %7D%0A%0A%09const domain = await domains.get(domainId)%0A%0A%09if (domain == null) throw createError(404, 'Unknown domain')
+normalizeSiteLocation = (siteLocation) =%3E %7B
 %0A%0A%09if (
-data.
 site
@@ -1180,27 +1180,14 @@
 %0A%0A%09%09
-data.siteLocation =
+return
  nor
@@ -1200,13 +1200,8 @@
 Url(
-data.
 site
@@ -1304,16 +1304,695 @@
 r)%0A%0A%09%7D%0A%0A
+%7D%0A%0Aconst normalizeSiteReferrer = (siteReferrer) =%3E %7B%0A%0A%09// The siteReferrer is optional%0A%09if (siteReferrer == null) return siteReferrer%0A%0A%09try %7B%0A%0A%09%09return normalizeUrl(siteReferrer)%0A%0A%09%7D catch (err) %7B%0A%0A%09%09throw createError(400, %60Failed to normalize %5C%60siteReferrer%5C%60%60, err)%0A%0A%09%7D%0A%0A%7D%0A%0Aconst add = async (req, res) =%3E %7B%0A%0A%09const %7B domainId %7D = req.params%0A%09const clientId = identifier(req, domainId)%0A%09const data = %7B ...await json(req), clientId, domainId %7D%0A%0A%09const domain = await domains.get(domainId)%0A%0A%09if (domain == null) throw createError(404, 'Unknown domain')%0A%0A%09data.siteLocation = normalizeSiteLocation(data.siteLocation)%0A%09data.siteReferrer = normalizeSiteReferrer(data.siteReferrer)%0A%0A
 %09let ent

Normalize site referrer