
package org.tio.sitexxx.view.http;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.http.common.HeaderName;
import org.tio.http.common.HeaderValue;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.http.common.session.limiter.SessionRateLimiter;
import org.tio.http.common.session.limiter.SessionRateVo;
import org.tio.utils.SystemTimer;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class WebViewSessionRateLimiter implements SessionRateLimiter {
	private static Logger log = LoggerFactory.getLogger(WebViewSessionRateLimiter.class);

	public static final WebViewSessionRateLimiter me = new WebViewSessionRateLimiter();

	private final Map<String, Integer> extAllowCountMap = new HashMap<>();

	/**
	 * key:   访问路径<br>
	 * value: 相邻两次访问必须间隔的最小时间，单位：毫秒<br>
	 */
	private final Map<String, Integer> map = new HashMap<>();

	/**
	 * js文件，每分钟默认允许访问的次数
	 */
	private final int DEFAULT_JS_ALLOW_COUNT = 50;

	/**
	 * css文件，每分钟默认允许访问的次数
	 */
	private final int DEFAULT_CSS_ALLOW_COUNT = 50;

	/**
	 * html文件，每分钟默认允许访问的次数
	 */
	private final int DEFAULT_HTML_ALLOW_COUNT = 40;

	private HttpResponse response;

	private WebViewSessionRateLimiter() {
		extAllowCountMap.put("html", DEFAULT_HTML_ALLOW_COUNT);
		extAllowCountMap.put("js", DEFAULT_JS_ALLOW_COUNT);
		extAllowCountMap.put("css", DEFAULT_CSS_ALLOW_COUNT);

		response = new HttpResponse();
		response.addHeader(HeaderName.Content_Type, HeaderValue.Content_Type.TEXT_HTML_HTML);
		response.setBody("操作太快，请稍后操作".getBytes(StandardCharsets.UTF_8));
		response.addHeader(HeaderName.Content_Type, HeaderValue.Content_Type.TEXT_PLAIN_JSON);
	}

	@Override
	public boolean allow(HttpRequest request, SessionRateVo sessionRateVo) {
		String path = request.getRequestLine().getPath();

		int allowCount = 9999999;
		if (sessionRateVo.getAccessCount().get() > allowCount) {
			log.error("path({}), access count of curr session({}) is greater than allow count({})", path, sessionRateVo.getAccessCount().get(), allowCount);
			return false;
		}

		Integer iv = map.get(path);
		if (iv != null) {
			if (SystemTimer.currTime - sessionRateVo.getLastAccessTime() < iv) {
				log.error("path({}), curr time ({}) - last access time ({}) < iv({})", path, SystemTimer.currTime, sessionRateVo.getLastAccessTime(), iv);
				return false;
			}
		}

		return true;
	}

	@Override
	public HttpResponse response(HttpRequest request, SessionRateVo sessionRateVo) {
		return response;
	}

}
