package project.web.generic.csv;

import java.io.IOException;

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

import org.apache.logging.log4j.LogManager;

import core.util.BooleanUtil;
import online.context.check.InputCheck;
import online.struts.action.RestAction;
import online.struts.action.UniForm;
import project.check.TopMessage;
import project.check.attribute.HanEisuCheck;
import project.check.attribute.LongNumeralCheck;
import project.check.existence.MustCheck;
import project.check.master.MasterCheck;
import project.svc.generic.CsvService;
import project.svc.generic.csv.extract.QueryBuilder;
import project.web.DownloadAction;
import project.web.InstanceFactory;

/**
 * 汎用CSV抽出アクション
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public final class ExportAction implements RestAction, DownloadAction, CsvAction {

	/** キー項目 */
	private static final String ID = "Id";
	/** ユーザパターン名 */
	private static final String USER_PATTERN_NAME = "UserPatternName";
	/** ヘッダー区分 */
	private static final String HEADER = "Header";

	/**
	 * 主処理
	 *
	 * @param uf 汎用フォーム
	 * @param request HttpServletRequestオブジェクト
	 * @param response HttpServletResponseオブジェクト
	 * @return 処理結果
	 */
	public String get(final UniForm uf, final HttpServletResponse response,
			final HttpServletRequest request) {

		select(uf);

		try {
			final var schema = getSchema(uf);
			if (schema == null) {
				if (!response.isCommitted()) {
					response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
					response.flushBuffer();
				}
				return null;
			}

			//DB情報取得
			final var jdq = InstanceFactory.create(CsvService.class, uf);
			jdq.setSchema(schema);
			jdq.showTitle(BooleanUtil.toBool(uf.getString(HEADER)));
			jdq.setTitle(QueryBuilder.getTitle(uf.getStringArray(OUTPUT_FLG),
							uf.getStringArray(ITEM_LABEL)));

			jdq.setOutputStream(response.getOutputStream());

			// httpヘッダ出力
			putHttpHeader(jdq, uf.getString(USER_PATTERN_NAME).trim(), request, response);

			outputCsv(jdq, uf);

			response.flushBuffer();

		} catch (final IOException ex) {
			LogManager.getLogger().info(ex.getMessage());
		}

		return null;
	}

	/**
	 * データ選択
	 * @param uf 汎用フォーム
	 */
	private void select(final UniForm uf) {
		if (!uf.hasValue(ID)) {
			final var ic = InstanceFactory.create(InputCheck.class, uf);
			ic.add(ID, new MustCheck(), new LongNumeralCheck());
			ic.add(HEADER, new HanEisuCheck());
			ic.populate();

			ic.onError(new TopMessage("ZZ000000005"));
			ic.add(ID, new MasterCheck(null, "project.svc.generic.csv.extract.SelectHeader"));
			ic.check();

			select("project.svc.generic.csv.extract.SelectHeader", uf);
			select("project.svc.generic.csv.extract.SelectCondition", uf);
			select("project.svc.generic.csv.extract.SelectItem", uf);
		}
	}

	/**
	 * httpヘッダ設定
	 * @param cs CsvService
	 * @param file ファイル名
	 * @param request リクエスト
	 * @param response レスポンス
	 */
	private void putHttpHeader(final CsvService cs, final String file,
			final HttpServletRequest request, final HttpServletResponse response) {
		final var name = file.replaceAll("[\\\\/:*?\"<>|：￥／？＊［］\\[\\]]", "") + ".csv";
		setHttpHeader(name, name, request, response);
		response.setContentType(response.getContentType() + "; "
				+ toCsvHeaderQuery(cs.isTitled()) + "; charset=" + cs.getCharset());
	}

	/**
	 * CSV出力
	 * @param jdq CSVサービス
	 * @param model 汎用モデル
	 */
	private void outputCsv(final CsvService jdq, final UniForm model) {
		final var qb = getQueryBuilder(model);
		jdq.setQuery(qb.build());
		jdq.search();
	}
}
