package project.web.generic.csv;

import batch.controller.JobRequestor;
import batch.status.Job;
import online.context.check.InputCheck;
import online.struts.action.BrowseAction;
import online.struts.action.UniForm;
import project.check.TopMessage;
import project.check.attribute.HanEisuCheck;
import project.check.attribute.LongNumeralCheck;
import project.check.attribute.NumberCheck;
import project.check.attribute.NumeralCheck;
import project.check.existence.MustCheck;
import project.check.range.LengthRangeCheck;
import project.master.MsgUtil;
import project.svc.generic.QueryService;
import project.svc.generic.RepeatService;
import project.web.InstanceFactory;

/**
 * CSV一括登録
 * @author Tadashi Nakayama
 */
public final class BatchAction implements BrowseAction, CsvAction {

	/** ID */
	private static final String ID = "Id";
	/** 選択パターンID */
	private static final String ID_SELECT = "SelectId";
	/** 定期起動ID */
	private static final String ID_REPEAT = "RepeatId";
	/** パターンID */
	private static final String ID_USER_PATTERN = "UserPatternId";
	/** 起動間隔 */
	private static final String INTERVAL = "Interval";
	/** 起動時 */
	private static final String HOUR = "Hour";
	/** 起動分 */
	private static final String MINUTE = "Minute";
	/** 起動曜日 */
	private static final String WEEK = "Week";
	/** 起動月日 */
	private static final String DAY = "YearMonthDay";
	/** 登録名称 */
	private static final String BATCH_NAME = "BatchName";
	/** VERSION */
	private static final String VERSION = "Version";
	/** 定期起動VERSION */
	private static final String VERSION_REPEAT = "RepeatVersion";

	/**
	 * 表示処理
	 *
	 * @param model 汎用データモデル
	 * @return 処理結果
	 */
	public String get(final UniForm model) {
		if (model.hasQueryString()) {
			final var ic = InstanceFactory.create(InputCheck.class, model);
			ic.add(ID, new MustCheck());
			ic.add(ID, new LongNumeralCheck());
			ic.populate();

			select("project.svc.generic.csv.batch.SelectBatch", model);
			model.setValue(ID_SELECT, model.getString(ID_USER_PATTERN).split(","));
		}

		return ID_VIEW;
	}

	/**
	 * 登録処理
	 * @param model 汎用データモデル
	 * @return 処理結果
	 */
	public String register(final UniForm model) {

		checkRegister(model);

		final var select = model.getStringArray(ID_SELECT);
		if (50 < select.length) {
			MsgUtil.putTopMessage(model, "ZZ000000005");
			return ID_NG;
		}

		model.setValue(ID_USER_PATTERN, String.join(",", select));

		if (!setRepeat(model)) {
			return ID_NG;
		}

		if (!model.hasValue(ID)) {
			select("project.svc.generic.csv.define.SelectId", model);
			update("project.svc.generic.csv.batch.InsertBatch", model);
		} else {
			if (1 != update("project.svc.generic.csv.batch.UpdateBatch", model)) {
				MsgUtil.putTopMessage(model, "ZZ000000019");
				return ID_NG;
			}
		}

		MsgUtil.putTopMessage(model, "ZZ000000020");
		return ID_OK;
	}

	/**
	 * 定期起動設定処理
	 * @param model 汎用モデル
	 * @return 処理結果
	 */
	private boolean setRepeat(final UniForm model) {
		final var rs = InstanceFactory.create(RepeatService.class, model);
		rs.setJobId("ExtractBatch");
		rs.setJobName("汎用CSV一括出力");
		if (model.getString(INTERVAL).isEmpty()) {
			if (model.hasValue(ID_REPEAT)) {
				if (!rs.delete(model.getNumber(ID_REPEAT), model.getNumber(VERSION_REPEAT))) {
					MsgUtil.putTopMessage(model, "ZZ000000019");
					return false;
				}
			}
		} else {
			if (model.hasValue(ID_REPEAT)) {
				model.setValue(ID_REPEAT, rs.insert());
			} else {
				if (!rs.update(model.getNumber(ID_REPEAT), model.getNumber(VERSION_REPEAT))) {
					MsgUtil.putTopMessage(model, "ZZ000000019");
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * 登録用チェック
	 * @param model UniForm
	 */
	private void checkRegister(final UniForm model) {
		final var ic = InstanceFactory.create(InputCheck.class, model);
		ic.onError(new TopMessage("ZZ000000005"));
		ic.add(ID, new LongNumeralCheck());
		ic.add(ID_SELECT, new MustCheck(), new NumberCheck());
		ic.add(INTERVAL, new HanEisuCheck());
		ic.add(HOUR, new NumberCheck(), new LengthRangeCheck(0, 2));
		ic.add(MINUTE, new NumberCheck(), new LengthRangeCheck(0, 2));
		ic.add(WEEK, new NumberCheck(), new LengthRangeCheck(0, 1));
		ic.add(DAY, new NumberCheck(), new LengthRangeCheck(0, 8));
		ic.add(BATCH_NAME, new MustCheck(), new LengthRangeCheck(1, 128));
		ic.add(VERSION, new NumeralCheck());
		ic.add(ID_REPEAT, new LongNumeralCheck());
		ic.add(VERSION_REPEAT, new NumeralCheck());
		ic.populate();
	}

	/**
	 * 一括登録削除処理
	 * @param model 汎用モデル
	 * @return 処理結果
	 */
	public String delete(final UniForm model) {
		final var ic = InstanceFactory.create(InputCheck.class, model);
		ic.onError(new TopMessage("ZZ000000005"));
		ic.add(ID, new MustCheck());
		ic.add(ID, new LongNumeralCheck());
		ic.add(ID_REPEAT, new MustCheck());
		ic.add(ID_REPEAT, new LongNumeralCheck());
		ic.populate();

		if (1 != update("project.svc.generic.csv.batch.DeleteBatch", model)) {
			MsgUtil.putTopMessage(model, "ZZ000000019");
			return ID_NG;
		}
		update("project.svc.generic.csv.batch.DeleteRepeat", model);

		MsgUtil.putTopMessage(model, "ZZ000000020");
		return ID_VIEW;
	}

	/**
	 * 出力依頼処理
	 * @param model 汎用モデル
	 * @return 処理結果
	 */
	public String output(final UniForm model) {
		final var ic = InstanceFactory.create(InputCheck.class, model);
		ic.onError(new TopMessage("ZZ000000005"));
		ic.add(ID, new MustCheck());
		ic.add(ID, new LongNumeralCheck());
		ic.populate();

		final Job job = getJob(model);
		if (job == null) {
			MsgUtil.putTopMessage(model, "ZZ000000013");
			return ID_NG;
		}

		JobRequestor.requestJob(job);

		MsgUtil.putTopMessage(model, "ZZ000000020");
		return ID_VIEW;
	}

	/**
	 * View用処理
	 * @param model 汎用モデル
	 */
	public void view(final UniForm model) {
		select("project.svc.generic.csv.batch.SelectBatchList", model);
		select("project.svc.generic.csv.extract.SelectMyPattern", model);
	}

	/**
	 * Job作成
	 * @param model 汎用モデル
	 * @return Job
	 */
	private Job getJob(final UniForm model) {
		final var ql = InstanceFactory.create(QueryService.class, model);
		ql.setQueryFile("project.svc.generic.csv.batch.SelectBatch");
		if (!ql.search()) {
			return null;
		}

		final var job = InstanceFactory.create(Job.class, model);
		job.setExecParam(ID_USER_PATTERN + "=" + ql.getResultModel().getString(ID_USER_PATTERN));
		job.setJobId("ExtractBatch");
		job.setJobName(ql.getResultModel().getString(BATCH_NAME));
		return job;
	}
}
