function makeCacheControlHeader({
	mode = 'public',
	maxAgeSeconds = -1,
	staleIfErrorSeconds = -1,
	staleWhileRevalidateSeconds = -1,
	immutable = false,
}) {
	const parts = [];
	if(mode) {
		parts.push(mode);
	}
	if(maxAgeSeconds >= 0) {
		parts.push(`max-age=${maxAgeSeconds}`);
	}
	if(staleIfErrorSeconds >= 0) {
		parts.push(`stale-if-error=${staleIfErrorSeconds}`);
	}
	if(staleWhileRevalidateSeconds >= 0) {
		parts.push(`stale-while-revalidate=${staleWhileRevalidateSeconds}`);
	}
	if(immutable) {
		parts.push('immutable');
	}
	return parts.join(', ');
}

export class RequestHandler {
	constructor(method, matcher, handleFn) {
		this.method = method;
		this.matcher = matcher;
		this.handleFn = handleFn;
		this.cacheControl = '';
		this.allowAllOrigins = false;
		this.staticHeaders = [];
		this.info = `Custom handler at ${this.method} ${this.matcher}`;
	}

	setCache(options) {
		this.cacheControl = options ? makeCacheControlHeader(options) : '';
		return this;
	}

	setCrossOrigin(allowAll) {
		this.allowAllOrigins = allowAll;
		return this;
	}

	addHeader(name, value) {
		this.staticHeaders.push({ name, value });
		return this;
	}

	applyCommonHeaders(req, res) {
		if(this.allowAllOrigins) {
			res.setHeader('Access-Control-Allow-Origin', '*');
		}
		if(this.cacheControl) {
			res.setHeader('Cache-Control', this.cacheControl);
		}
		for(const header of this.staticHeaders) {
			res.setHeader(header.name, header.value);
		}
	}

	apply(req, res, info) {
		if(req.method !== this.method) {
			return false;
		}
		const match = this.matcher.exec(req.url);
		if(!match) {
			return false;
		}
		if(this.handle(req, res, Object.assign({match}, info)) === false) {
			return false;
		}
		return true;
	}

	handle(req, res, info) {
		return this.handleFn(req, res, info);
	}

	printInfo(target) {
		target.write(this.info + '\n');
	}

	begin() {
		return true;
	}

	close() {
		return true;
	}
}
