package project.web.generic.csv;

import common.db.ExclusiveException;
import core.exception.ThrowableUtil;
import online.model.Band;
import online.struts.action.UniForm;
import project.svc.generic.QueryService;
import project.svc.generic.UpdateService;
import project.svc.generic.csv.extract.QueryBuilder;
import project.web.InstanceFactory;

/**
 * CSVアクションユーティリティ
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
interface CsvAction {

	/** 基本クエリ項目 */
	String QUERY_FROM = "QueryFrom";
	/** 基本条件項目 */
	String QUERY_WHERE = "QueryWhere";
	/** 出力項目値項目 */
	String ITEM_VALUE = "ItemValue";
	/** 出力項目名項目 */
	String ITEM_LABEL = "ItemLabel";
	/** 集約項目 */
	String GROUP_FLG = "GroupFlg";
	/** 集計項目 */
	String AGGREGATION_KBN = "AggregationKbn";
	/** 順序項目 */
	String ORDER_SORT = "OrderSort";
	/** 順序区分項目 */
	String ORDER_KBN = "OrderKbn";
	/** 出力項目 */
	String OUTPUT_FLG = "OutputFlg";
	/** 条件数項目 */
	String CONDITION_COLUMN = "ConditionColumn";
	/** 演算項目 */
	String OPERATOR = "Operator";
	/** 条件値項目 */
	String CONDITION = "Condition";
	/** 条件項目名項目 */
	String ITEM_NAME = "ItemName";

	/**
	 * 選択処理
	 *
	 * @param query クエリ
	 * @param model 汎用モデル
	 * @return 選択結果
	 */
	default boolean select(final String query, final UniForm model) {
		final var ql = InstanceFactory.create(QueryService.class, model);
		ql.setQueryFile(query);
		final var ret = ql.search();
		model.putAll(ql.getResultModel());
		return ret;
	}

	/**
	 * 更新処理
	 *
	 * @param query クエリ
	 * @param model 汎用モデル
	 * @return 処理件数
	 */
	default int update(final String query, final UniForm model) {
		final var ql = InstanceFactory.create(UpdateService.class, model);
		ql.setQueryFile(query);
		try {
			return ql.update(model);
		} catch (final ExclusiveException ex) {
			ThrowableUtil.warn(ex);
			return 0;
		}
	}

	/**
	 * 詳細項目更新処理
	 *
	 * @param query クエリ
	 * @param model 汎用モデル
	 * @param item サイズ判定項目名
	 */
	default void updateArray(final String query, final UniForm model, final String item) {
		final var ql = InstanceFactory.create(UpdateService.class, model);
		ql.setQueryFile(query);
		try {
			Band.stream(model, item).forEach(band -> {
				final var map = band.toMap();
				map.put("DtlNo", band.index() + 1);
				ql.update(map);
			});
		} catch (final ExclusiveException ex) {
			ThrowableUtil.warn(ex);
		}
	}

	/**
	 * スキーマ名取得
	 *
	 * @param model 汎用モデル
	 * @return スキーマ名
	 */
	default String getSchema(final UniForm model) {
		if (select("project.svc.generic.csv.extract.SelectQuery", model)) {
			return model.getString("SchemaName");
		}
		return null;
	}

	/**
	 * クエリビルダ取得
	 *
	 * @param model 汎用モデル
	 * @return クエリビルダ
	 */
	default QueryBuilder getQueryBuilder(final UniForm model) {
		final var qb = new QueryBuilder(model.getString(QUERY_FROM),
						model.getString(QUERY_WHERE), model.getStringArray(ITEM_VALUE),
						model.getStringArray(ITEM_LABEL));
		qb.setGroup(model.getStringArray(GROUP_FLG));
		qb.setAggregation(model.getStringArray(AGGREGATION_KBN));
		qb.setOrderSort(model.getNumberArray(ORDER_SORT));
		qb.setOrderKbn(model.getStringArray(ORDER_KBN));
		qb.setColumnOutput(model.getStringArray(OUTPUT_FLG));
		final var size = model.hasValue(CONDITION_COLUMN)
				? model.getNumber(CONDITION_COLUMN).intValue() : model.getArraySize(ITEM_NAME);
		qb.setCondition(size, model.getStringArray(OPERATOR),
						model.getStringArray(CONDITION), model.getStringArray(ITEM_NAME));
		return qb;
	}
}
