package online.struts.chain.command;

import java.util.Objects;

import org.apache.commons.chain2.Processing;
import org.apache.logging.log4j.LogManager;
import org.apache.struts.chain.commands.ActionCommandBase;
import org.apache.struts.chain.contexts.ActionContext;
import org.apache.struts.chain.contexts.ServletActionContext;

import core.exception.PhysicalException;
import online.filter.FilterUtil;
import online.struts.mapping.RequestMapping;

/**
 * サーブレットパスプロセッサ
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public final class ServletPathProcessor implements ActionCommandBase {

	/** ServletPath設定項目名 */
	private String name;
	/** 許可値 */
	private String[] value;

	/**
	 * @return the name
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * @param val the name to set
	 */
	public void setName(final String val) {
		this.name = val;
	}

	/**
	 * @return the value
	 */
	public String getValue() {
		return String.join(",", this.value);
	}

	/**
	 * @param val the value to set
	 */
	public void setValue(final String val) {
		if (!Objects.toString(val, "").isEmpty()) {
			this.value = val.split(",");
		}
	}

	/**
	 * @see org.apache.struts.chain.commands.ActionCommandBase
	 * #execute(org.apache.struts.chain.contexts.ActionContext)
	 */
	@Override
	public Processing execute(final ActionContext<String, Object> context) {
		// キャスト
		if (!ServletActionContext.class.isInstance(context)) {
			LogManager.getLogger().error(context);
			throw new IllegalStateException(String.valueOf(context));
		}
		final var sac = ServletActionContext.class.cast(context);

		final var ac = context.getActionConfig();
		if (!RequestMapping.class.isInstance(ac)) {
			return Processing.CONTINUE;
		}
		final var mapping = RequestMapping.class.cast(ac);

		if (sac.getForwardConfig() != null || RequestCommand.isException(sac)
				|| !RequestCommand.isFirst(sac, this.getClass())) {
			return Processing.CONTINUE;
		}

		final var cpath = sac.getRequest().getContextPath();
		final var uri = FilterUtil.getRequestURI(sac.getRequest());
		if (this.value == null || this.value.length == 0) {
			if (uri.startsWith(cpath + mapping.getPath())) {
				return Processing.CONTINUE;
			}
		} else {
			for (final var path : this.value) {
				if (uri.startsWith(cpath + "/" + path + mapping.getPath())) {
					if (this.name != null) {
						sac.getRequest().setAttribute(this.name, path);
					}
					return Processing.CONTINUE;
				}
			}
		}

		throw new PhysicalException("wrong servlet path", null);
	}
}
