package project.web.job;

import java.io.IOException;

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

import online.context.check.InputCheck;
import online.struts.action.UniForm;

import org.apache.logging.log4j.LogManager;

import project.check.attribute.NumeralCheck;
import project.web.DownloadBase;
import project.web.InstanceFactory;
import batch.status.Job;
import batch.status.JobFile;
import batch.status.JobFileStatus;
import batch.status.JobStatus;

import common.db.JdbcSource;
import common.db.jdbc.Jdbc;

import core.config.Env;
import core.config.Factory;

/**
 * ダウンロードアクション親
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public abstract class DownloadJobFile extends DownloadBase {

	/** ジョブ連番 */
	private static final String TAG_JOB_SEQ = "JobSeq";
	/** バッチ連番 */
	private static final String TAG_DTL_SEQ = "BatSeq";
	/** ファイル連番 */
	private static final String TAG_FILE_SEQ = "FileSeq";

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

		InputCheck ic = InstanceFactory.create(InputCheck.class, uf);
		ic.add(TAG_JOB_SEQ, new NumeralCheck());
		ic.add(TAG_DTL_SEQ, new NumeralCheck());
		ic.add(TAG_FILE_SEQ, new NumeralCheck());
		ic.populate();

		try {
			// ジョブ情報取得
			Job job = getJobInfo(uf.getNumber(TAG_JOB_SEQ));
			// ファイル情報取得
			JobFile finfo = getFileInfo(uf.getNumber(TAG_JOB_SEQ),
							uf.getNumber(TAG_DTL_SEQ), uf.getNumber(TAG_FILE_SEQ));
			if (job == null || finfo == null || !canDownload(uf, job)) {
				if (!response.isCommitted()) {
					response.sendError(HttpServletResponse.SC_NOT_FOUND);
					response.flushBuffer();
				}
				return null;
			}

			// ダウンロード名作成
			super.setHttpHeader(finfo.getFileName(), finfo.getDownloadName(), request, response);

			response.setContentLength(Long.valueOf(finfo.getFileSize()).intValue());

			// ダウンロード
			fileDownload(job, finfo, request, response);

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

		return null;
	}

	/**
	 * ファイルダウンロード判断
	 *
	 * @param model 汎用モデル
	 * @param job ジョブ情報
	 * @return ダウンロード可能の場合 true を返す。
	 */
	protected abstract boolean canDownload(final UniForm model, final Job job);

	/**
	 * ファイルダウンロード処理
	 *
	 * @param job ジョブ情報
	 * @param finfo ダウンロードファイル情報
	 * @param request HttpServletRequestオブジェクト
	 * @param response HttpServletResponseオブジェクト
	 */
	protected abstract void fileDownload(final Job job, final JobFile finfo,
					final HttpServletRequest request, final HttpServletResponse response);

	/**
	 * ジョブ情報取得
	 *
	 * @param jobseq ジョブ連番
	 * @return ジョブ情報
	 */
	private Job getJobInfo(final Number jobseq) {
		if (jobseq != null) {
			try (Jdbc conn = JdbcSource.getConnection()) {
				JobStatus js = Factory.create(JobStatus.class);
				return js.getJob(conn, jobseq.longValue());
			}
		}
		return null;
	}

	/**
	 * ファイル取得
	 *
	 * @param jobseq ジョブ連番
	 * @param dtlseq ジョブ詳細連番
	 * @param fileseq ファイル連番
	 * @return ファイル情報
	 */
	private JobFile getFileInfo(final Number jobseq, final Number dtlseq, final Number fileseq) {
		if (jobseq == null) {
			return null;
		}

		// 指定無し時先頭
		int dseq = Env.getEnv("Download.DefaultDtlSeq", 1);
		if (dtlseq != null) {
			dseq = dtlseq.intValue();
		}
		// 指定無し時先頭
		int fseq = Env.getEnv("Download.DefaultFileSeq", 1);
		if (fileseq != null) {
			fseq = fileseq.intValue();
		}

		JobFileStatus jfs = Factory.create(JobFileStatus.class);

		try (Jdbc conn = JdbcSource.getConnection()) {
			return jfs.countUpDownload(conn, jobseq.longValue(), dseq, fseq);
		}
	}
}
