package online.context;

import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import online.model.ModelUtil;
import online.model.UniModel;

/**
 * リクエストパラメータ
 *
 * @author Tadashi Nakayama
 */
public class RequestParameter implements Serializable {

	/** serialVersionUID */
	private static final long serialVersionUID = 1L;

	/** パラメタマップ */
	private final Map<String, String[]> param;

	/**
	 * コンストラクタ
	 *
	 * @param map パラメータマップ
	 */
	public RequestParameter(final Map<String, String[]> map) {
		this.param = map;
	}

	/**
	 * パラメタマップ取得
	 *
	 * @return パラメタマップ
	 */
	public Set<String> keySet() {
		return this.param.keySet();
	}

	/**
	 * パラメタマップ存在確認
	 *
	 * @param key キー
	 * @return 存在した場合 true を返す。
	 */
	public boolean containsKey(final String key) {
		return this.param.containsKey(key);
	}

	/**
	 * 項目削除
	 *
	 * @param key キー
	 */
	public void remove(final String key) {
		this.param.remove(key);
	}

	/**
	 * パラメタマップから値取得
	 *
	 * @param key キー
	 * @return 値
	 */
	public String getValue(final String key) {
		final var obj = this.param.get(key);
		if (obj != null && 0 < obj.length) {
			return obj[0];
		}
		this.param.put(key, new String[0]);
		return null;
	}

	/**
	 * パラメタマップから値取得
	 *
	 * @param key キー
	 * @return 値
	 */
	public String[] getArrayValue(final String key) {
		final var obj = this.param.get(key);
		if (obj != null) {
			return obj.clone();
		}
		final String[] ret = {};
		this.param.put(key, ret);
		return ret;
	}

	/**
	 * パラメタマップに値設定（存在しない場合のみ）
	 *
	 * @param key キー
	 * @param val 値
	 */
	public void setValue(final String key, final String... val) {
		if (this.param.get(key) == null) {
			this.param.put(key, (val != null) ? val.clone() : null);
		}
	}

	/**
	 * パラメタマップ設定
	 *
	 * @param uf 汎用フォーム
	 */
	public void setParameterTo(final UniModel uf) {
		setParameterTo(uf, Collections.emptySet());
	}

	/**
	 * パラメタマップ設定
	 *
	 * @param uf 汎用フォーム
	 * @param exclusion 対象外集合
	 */
	public void setParameterTo(final UniModel uf, final Set<String> exclusion) {
		if (uf != null) {
			for (final var me : this.param.entrySet()) {
				if (ModelUtil.canSet(me.getKey())
						&& !UniModel.class.equals(uf.getValueClass(me.getKey()))
						&& !exclusion.contains(me.getKey())) {
					uf.setValue(me.getKey(), me.getValue());
				}
			}
		}
	}
}
