package com.udapsoft.modular.web.tags;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.PageContext;

import kr.co.hsnc.common.config.WAFConfig;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.util.ExpressionEvaluationUtils;

import com.udapsoft.modular.core.util.StringUtils;
import com.udapsoft.modular.web.template.TemplateUtils;

public abstract class TemplateBasedRequestContextAwareTag extends RequestContextAwareTagExtends {
	private static final long serialVersionUID = -5525886194286370889L;
	private static final String MODULAR_WEB_TAG_TEMPLATE_PATH = "modular.web.tag.template.path";
	private static final String MODULAR_WEB_TAG_TEMPLATE_LIST = "modular.web.tag.template.list";
	private static final int UNSUPPORTED_OPERATION = 5;

	protected int doStartTagInternal() throws Exception {
		Map model = new HashMap();
		int returnValue = doBuildModelForStartTag(model);
		Class<?> c = getClass();

		String templateName = getTemplateName(c.getName(), true);
		TemplateUtils.generate(templateName, c, model, this.pageContext.getOut());
		return returnValue;
	}

	protected abstract int doBuildModelForStartTag(Map paramMap)
			throws Exception;

	public int doEndTag() throws JspException {
		try {
			Map model = new HashMap();
			int returnValue = doBuildModelForEndTag(model);
			if (returnValue == 5) {
				return super.doEndTag();
			}
			Class<?> c = getClass();

			String templateName = getTemplateName(c.getName(), false);
			TemplateUtils.generate(templateName, c, model, this.pageContext.getOut());
			return returnValue;
		} catch (JspException ex) {
			this.logger.error(ex.getMessage(), ex);
			throw ex;
		} catch (RuntimeException ex) {
			this.logger.error(ex.getMessage(), ex);
			throw ex;
		} catch (Exception ex) {
			this.logger.error(ex.getMessage(), ex);
			throw new JspTagException(ex.getMessage());
		}
	}

	protected int doBuildModelForEndTag(Map model) throws Exception {
		return 5;
	}

	protected Locale getLocale() {
		return LocaleContextHolder.getLocaleContext().getLocale();
	}

	protected void evaluateStringAndSetModel(Map model, String attrName,
			PageContext pageContext) throws Exception {
		Object attrValue = PropertyUtils.getProperty(this, attrName);
		if ((attrValue instanceof String)) {
			String value = (String) attrValue;
			Object obj = null;
			if ((StringUtils.hasText(value)) && (value.indexOf("${") >= 0)) {
				try {
					obj = ExpressionEvaluationUtils.evaluate(attrName, value, pageContext);
				} catch (Exception e) {
					obj = value;
				}
				if ((obj instanceof String)) {
					BeanUtils.setProperty(this, attrName, obj);
				}
			} else {
				obj = value;
			}
			model.put(attrName, obj);
		} else {
			model.put(attrName, attrValue);
		}
	}

	protected boolean isSupportJsp20(Object o, Class type) {
		if (o == null) {
			return false;
		}
		if (o.getClass().isArray()) {
			return true;
		}
		return (type != null) && (type.isAssignableFrom(o.getClass()));
	}

	private String getTemplateName(String fqcn, boolean isStartTag) {
		int idx = fqcn.lastIndexOf(".");
		String templateName = (idx > 0 ? fqcn.substring(idx + 1) : fqcn)
				+ (isStartTag ? ".start.ftl" : ".end.ftl");

		String templatePath = null;

		String modularWebTagTemplateList = WAFConfig.get(MODULAR_WEB_TAG_TEMPLATE_LIST);
		if ((modularWebTagTemplateList != null)
				&& (modularWebTagTemplateList.contains(templateName))) {
			templatePath = WAFConfig.get(MODULAR_WEB_TAG_TEMPLATE_PATH);
		} else {
			templatePath = "ftl";
		}
		return templatePath + "/" + templateName;
	}
}
