###############################################################################
#                                                                             #
# Telize 1.07                                                                 #
# Copyright (c) 2013-2017, Frederic Cambus                                    #
# https://www.telize.com                                                      #
#                                                                             #
# Created: 2013-08-15                                                         #
# Last Updated: 2017-02-07                                                    #
#                                                                             #
# Telize is released under the BSD 2-Clause license.                          #
# See LICENSE file for details.                                               #
#                                                                             #
###############################################################################

server {
	# Configuration variables
	set $cors "true";
	set $cors_origin "*";

	server_name 127.0.0.1;

	# Uncomment when using Telize behind a load balancer
	# set_real_ip_from 10.0.0.0/8; # Put your load balancer IP range here
	# real_ip_header X-Forwarded-For;

	charset_types application/json;

	keepalive_timeout 0;
	gzip off;

	location ~ /ip$ {
		add_header Cache-Control no-cache;

		charset off;
		default_type text/plain;

		content_by_lua_block {
			ngx.say(ngx.var.remote_addr)
		}
	}

	location ~ /jsonip$ {
		charset utf-8;
		default_type application/json;

		content_by_lua_block {
			local cjson = require("cjson")

			local json = cjson.encode({
				ip = ngx.var.remote_addr
			})

			local callback = ngx.var.arg_callback

			if callback then
				ngx.say(callback, "(", json, ");")
			else
				ngx.say(json)
			end
		}
	}

	location ~ /geoip/?(?<ip>.*) {
		if ($ip = "") {
			set $ip $remote_addr;
		}

		# Uncomment when using Telize behind a load balancer, and
		# comment the directive setting X-Real-IP
		# proxy_set_header X-Forwarded-For $ip;

		proxy_set_header X-Real-IP $ip;
		proxy_set_header Host $host;
		proxy_pass $scheme://127.0.0.1/jsonify?callback=$arg_callback;
	}

	location /jsonify {
		set_real_ip_from 127.0.0.1;

		access_log off;

		charset utf-8;
		default_type application/json;

		if ($cors = "true") {
			add_header Access-Control-Allow-Origin $cors_origin;
		}

		content_by_lua_block {
			local cjson = require("cjson")
			local iconv = require("iconv")
			local cd = iconv.new("utf-8","iso-8859-15")

			ngx.header["Cache-Control"] = "no-cache";

			-- Check for invalid IP addresses
			if ngx.var.remote_addr == "127.0.0.1" then
				ngx.status = ngx.HTTP_BAD_REQUEST
				ngx.say(cjson.encode({
					code = 401,
					message = "Input string is not a valid IP address"
				}))
				ngx.exit(ngx.HTTP_OK)
			end

			local payload = {
				ip = ngx.var.remote_addr,
				country_code = ngx.var.geoip_city_country_code,
				country_code3 = ngx.var.geoip_city_country_code3,
				country = ngx.var.geoip_city_country_name,
				region = ngx.var.geoip_region_name,
				region_code = ngx.var.geoip_region,
				city = ngx.var.geoip_city,
				postal_code = ngx.var.geoip_postal_code,
				continent_code = ngx.var.geoip_city_continent_code,
				latitude = ngx.var.geoip_latitude,
				longitude = ngx.var.geoip_longitude,
				dma_code = ngx.var.geoip_dma_code,
				area_code = ngx.var.geoip_area_code,
				organization = ngx.var.geoip_org,
				timezone = ngx.var.geoip_timezone,
				offset = ngx.var.geoip_timezone_offset,
			}

			local callback = ngx.var.arg_callback

			-- Validate payload
			for item, value in pairs(payload) do
				if payload[item] == "" then
					payload[item] = nil
				end
			end

			-- Convert latitude and longitude to numeric values
			if payload.latitude ~= nil and payload.longitude ~= nil then
				payload.latitude = tonumber(payload.latitude)
				payload.longitude = tonumber(payload.longitude)
			end

			-- Convert city name to UTF-8 if it exists
			if payload.city ~= nil then
				payload.city = cd:iconv(payload.city)
			end

			-- Convert region name to UTF-8 if it exists
			if payload.region ~= nil then
				payload.region = cd:iconv(payload.region)
			end

			-- Convert organization name to UTF-8 if it exists
			if payload.organization ~= nil then
				payload.organization = cd:iconv(payload.organization)
			end

			local json = cjson.encode(payload)

			if callback ~= "" then
				ngx.say(callback, "(", json, ");")
			else
				ngx.say(json)
			end
		}
	}
}
