package project.web;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Optional;
import java.util.function.UnaryOperator;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import core.util.MojiUtil;
import core.util.bean.Pair;
import online.model.UniModel;
import online.view.ViewUtil;

/**
 * ダウンロードアクション
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public interface DownloadAction {

	/**
	 * ヘッダ設定
	 *
	 * @param fname ファイル名
	 * @param name ダウンロード名。指定した場合、attachmentになる。
	 * @param request HttpServletRequestオブジェクト
	 * @param response HttpServletResponseオブジェクト
	 */
	default void setHttpHeader(final String fname, final String name,
			final HttpServletRequest request, final HttpServletResponse response) {
		// レスポンスヘッダ設定
		final var mime = request.getServletContext().getMimeType(fname);
		response.setContentType(Optional.ofNullable(mime).orElse("application/octet-stream"));

		if (Objects.toString(name, "").isEmpty()) {
			response.setHeader("Content-Disposition",
							"inline; " + toDownloadName(fname, request));
		} else {
			response.setHeader("Content-Disposition",
							"attachment; " + toDownloadName(name, request));
		}

		response.setDateHeader("Expires", 0);
		response.setHeader("Cache-Control", "must-revalidate");
		response.setHeader("Pragma", "private");
	}

	/**
	 * CSVヘッダ判断
	 *
	 * @param model UniModel
	 * @return CSVヘッダ必要時 true を返す。
	 */
	default boolean needsTitle(final UniModel model) {
		return "present".equalsIgnoreCase(model.getString("header"));
	}

	/**
	 * CSVヘッダ文字列取得
	 *
	 * @param val ヘッダ有無フラグ
	 * @return CSVヘッダ文字列
	 */
	default String toCsvHeaderQuery(final boolean val) {
		return val ? "header=present" : "header=absent";
	}

	/**
	 * ダウンロード名取得
	 *
	 * @param name ファイル名
	 * @param request リクエスト
	 * @return ダウンロード名
	 */
	default String toDownloadName(final String name, final HttpServletRequest request) {

		final UnaryOperator<String> sjis = s -> {
			final String nm = MojiUtil.correctGarbled(s, MojiUtil.CHARSET_W31J);
			return "filename="
					+ new String(nm.getBytes(MojiUtil.CHARSET_W31J), StandardCharsets.ISO_8859_1);
		};

		final UnaryOperator<String> utf8 =
				s -> "filename*=" + StandardCharsets.UTF_8.name() + "''"
					+ ViewUtil.encode(s, StandardCharsets.UTF_8.name());

		final var list = new ArrayList<Pair<String, UnaryOperator<String>>>();
		list.add(Pair.of(".*Safari.*", (String s) -> ""));
		list.add(Pair.of(".*[MSIE|Trident|Chrome].*", sjis));

		final var agent = request.getHeader("User-Agent");
		final Optional<Pair<String, UnaryOperator<String>>> opt =
				list.stream().filter(p -> agent.matches(p.left())).findFirst();
		return opt.orElse(Pair.of(".*", utf8)).right().apply(name);
	}
}
