package online.struts.action;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

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

import online.struts.mapping.RequestMapping;

import org.apache.logging.log4j.LogManager;

import common.db.ExclusiveException;

import core.exception.LogicalException;
import core.exception.PhysicalException;

/**
 * ブラウザアクション
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public interface BrowseAction extends PerformAction {

	/** 更新完了後自画面 */
	String ID_UPDATED = "UPDATED";
	/** 更新対象無し後新規入力 */
	String ID_NG_REDIRECT = "NG_REDIRECT";
	/** システムエラー */
	String ID_SYS_ERROR = "SYSTEM_ERROR";

	/**
	 * 処理振分け
	 *
	 * @param mapping RequestMappingオブジェクト
	 * @param uf 汎用フォーム
	 * @param request HttpServletRequestオブジェクト
	 * @param response HttpServletResponseオブジェクト
	 * @return 処理結果
	 */
	@Override
	default String perform(final RequestMapping mapping, final UniForm uf,
			final HttpServletRequest request, final HttpServletResponse response) {
		try {
			// 実処理
			final Method mt = RequestMapping.getActionMethod(this.getClass(),
							uf.getActionParameter().getAid(), UniForm.class);
			return String.class.cast(mt != null ? mt.invoke(this, uf) : ID_VIEW);
		} catch (final IllegalAccessException ex) {
			LogManager.getLogger().error(ex.getMessage(), ex);
			throw new PhysicalException(ex);
		} catch (final InvocationTargetException ex) {
			final Throwable e = ex.getCause();
			if (LogicalException.class.isInstance(e)) {
				LogManager.getLogger().info(e.getMessage());
				final LogicalException le = LogicalException.class.cast(e);
				String ret = le.getReturnCode();
				if (Objects.toString(ret, "").isEmpty()) {
					if (Objects.toString(le.getMessage(), "").isEmpty()) {
						ret = ID_SYS_ERROR;
					} else {
						ret = ID_NG;
					}
				}
				return ret;
			} else if (ExclusiveException.class.isInstance(e)) {
				throw ExclusiveException.class.cast(e);
			} else if (RuntimeException.class.isInstance(e)) {
				throw RuntimeException.class.cast(e);
			}
			throw new PhysicalException(e);
		}
	}
}
