{%- macro nginx_map(from_variable, to_variable, values, default) %}
map {{ from_variable }} {{ to_variable }} {
	{% for (from, to) in values.items() -%}
		{{ from }} {{ to }};
	{% endfor %}

	{%- if default -%}
		default {{ default }};
	{% endif %}
}
{%- endmacro %}

{%- macro server_block(bench_name, port, server_names, site_name, sites_path, ssl_certificate, ssl_certificate_key) %}
server {
	{% if ssl_certificate and ssl_certificate_key %}
	listen {{ port }} ssl;
	{% else %}
	listen {{ port }};
	{% endif %}

	server_name
		{% for name in server_names -%}
		{{ name }}
		{% endfor -%}
		;

	root {{ sites_path }};

	{% if allow_rate_limiting %}
	limit_conn per_host_{{ bench_name_hash }} 8;
	{% endif %}

	{% if ssl_certificate and ssl_certificate_key %}
	ssl on;
	ssl_certificate      {{ ssl_certificate }};
	ssl_certificate_key  {{ ssl_certificate_key }};
	ssl_session_timeout  5m;
	ssl_session_cache shared:SSL:10m;
	ssl_session_tickets off;
	ssl_stapling on;
	ssl_stapling_verify on;
	ssl_protocols TLSv1.2 TLSv1.3;
	ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
	ssl_ecdh_curve secp384r1;
	ssl_prefer_server_ciphers on;
	{% endif %}

	add_header X-Frame-Options "SAMEORIGIN";
	add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
	add_header X-Content-Type-Options nosniff;
	add_header X-XSS-Protection "1; mode=block";

	location /assets {
		try_files $uri =404;
	}

	location ~ ^/protected/(.*) {
		internal;
		try_files /{{ site_name }}/$1 =404;
	}

	location /socket.io {
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
		proxy_set_header X-Frappe-Site-Name {{ site_name }};
		proxy_set_header Origin $scheme://$http_host;
		proxy_set_header Host $host;

		proxy_pass http://{{ bench_name }}-socketio-server;
	}

	location / {

 		rewrite ^(.+)/$ $1 permanent;
  		rewrite ^(.+)/index\.html$ $1 permanent;
  		rewrite ^(.+)\.html$ $1 permanent;

		location ~ ^/files/.*.(htm|html|svg|xml) {
			add_header Content-disposition "attachment";
			try_files /{{ site_name }}/public/$uri @webserver;
		}

		try_files /{{ site_name }}/public/$uri @webserver;
	}

	location @webserver {
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header X-Frappe-Site-Name {{ site_name }};
		proxy_set_header Host $host;
		proxy_set_header X-Use-X-Accel-Redirect True;
		proxy_read_timeout {{ http_timeout or 120 }};
		proxy_redirect off;

		proxy_pass  http://{{ bench_name }}-frappe;
	}

	# error pages
	{% for error_code, error_page in error_pages.items() -%}

	error_page {{ error_code }} /{{ error_page.split('/')[-1] }};
	location /{{ error_code }}.html {
		root {{ '/'.join(error_page.split('/')[:-1]) }};
		internal;
	}

	{% endfor -%}

	# optimizations
	sendfile on;
	keepalive_timeout 15;
	client_max_body_size 50m;
	client_body_buffer_size 16K;
	client_header_buffer_size 1k;

	# enable gzip compresion
	# based on https://mattstauffer.co/blog/enabling-gzip-on-nginx-servers-including-laravel-forge
	gzip on;
	gzip_http_version 1.1;
	gzip_comp_level 5;
	gzip_min_length 256;
	gzip_proxied any;
	gzip_vary on;
	gzip_types
		application/atom+xml
		application/javascript
		application/json
		application/rss+xml
		application/vnd.ms-fontobject
		application/x-font-ttf
		application/font-woff
		application/x-web-app-manifest+json
		application/xhtml+xml
		application/xml
		font/opentype
		image/svg+xml
		image/x-icon
		text/css
		text/plain
		text/x-component
		;
		# text/html is always compressed by HttpGzipModule
}

{% if ssl_certificate and ssl_certificate_key -%}
	# http to https redirect
	server {
		listen 80;
		server_name
			{% for name in server_names -%}
			{{ name }}
			{% endfor -%}
			;

		return 301 https://$host$request_uri;
	}

{% endif %}

{%- endmacro -%}

upstream {{ bench_name }}-frappe {
	server 127.0.0.1:{{ webserver_port or 8000 }} fail_timeout=0;
}

upstream {{ bench_name}}-socketio-server {
	server 127.0.0.1:{{ socketio_port or 3000 }} fail_timeout=0;
}

{% if allow_rate_limiting %}
limit_conn_zone $host zone=per_host_{{ bench_name_hash }}:{{ limit_conn_shared_memory }}m;
{% endif %}

# setup maps
{%- set site_name_variable="$host" %}
{% if sites.domain_map -%}
	{# we append these variables with a random string as there could be multiple benches #}
	{%- set site_name_variable="$site_name_{0}".format(random_string) -%}
	{{ nginx_map(from_variable="$host", to_variable=site_name_variable, values=sites.domain_map, default="$host") }}
{%- endif %}

# server blocks
{% if sites.that_use_dns -%}

	{{ server_block(bench_name, port=80, server_names=sites.that_use_dns, site_name=site_name_variable, sites_path=sites_path) }}

{%- endif %}

{% if sites.that_use_wildcard_ssl -%}

	{{ server_block(bench_name, port=443, server_names=sites.that_use_wildcard_ssl,
		site_name=site_name_variable, sites_path=sites_path,
		ssl_certificate=sites.wildcard_ssl_certificate,
		ssl_certificate_key=sites.wildcard_ssl_certificate_key) }}

{%- endif %}

{%- if sites.that_use_ssl -%}
	{% for site in sites.that_use_ssl -%}

		{{ server_block(bench_name, port=443, server_names=[site.domain or site.name],
				site_name=site_name_variable, sites_path=sites_path,
				ssl_certificate=site.ssl_certificate, ssl_certificate_key=site.ssl_certificate_key) }}

	{% endfor %}
{%- endif %}

{% if sites.that_use_port -%}
	{%- for site in sites.that_use_port -%}

		{{ server_block(bench_name, port=site.port, server_names=[site.name], site_name=site.name, sites_path=sites_path) }}

	{%- endfor %}
{% endif %}
