package it.mice.voila.runtime.springmvc.taglibs;

import it.mice.voila.runtime.springmvc.bean.PageStatus;

import javax.servlet.jsp.JspException;

import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.tags.form.TagWriter;
import it.mice.voila.runtime.springmvc.util.ExpressionEvaluationUtils;

public class TextareaTag extends
		org.springframework.web.servlet.tags.form.TextareaTag {

	public static final String MAXLENGTH_ATTRIBUTE = "maxLength";

	/**
	 * serial version UID
	 */
	private static final long serialVersionUID = 3232323232L;

	private TagWriter tagWriter;
	private String required = "false";
	private String disableDojo = null;
	private String forceEdit = null;

	private String protectIfPageStatusIs = null;
	private String protectIfPageStatusIsNot = null;
	
	private boolean fitContent = false;
	private boolean leftCharsIndicator = false;
	
	private Integer maxLength = null;

	private String useWysiwyg = "false";
	private String useCodeMirror = "false";
	
	/**
	 * @return the maxLength
	 */
	public Integer getMaxLength() {
		return maxLength;
	}
	
	/**
	 * @return the maxLength
	 */
	public String getMaxLengthAsString() {
		if (getMaxLength() != null) {
			return getMaxLength().toString();
		}
		return null;
	}

	/**
	 * @param maxLength the maxLength to set
	 */
	public void setMaxLength(Integer maxLength) {
		this.maxLength = maxLength;
	}

	/**
	 * @return the leftCharsIndicator
	 */
	public boolean isLeftCharsIndicator() {
		return leftCharsIndicator;
	}

	/**
	 * @param leftCharsIndicator the leftCharsIndicator to set
	 */
	public void setLeftCharsIndicator(boolean leftCharsIndicator) {
		this.leftCharsIndicator = leftCharsIndicator;
	}

	public String getProtectIfPageStatusIs() {
		return protectIfPageStatusIs;
	}

	public void setProtectIfPageStatusIs(String protectIfPageStatusIs) {
		this.protectIfPageStatusIs = protectIfPageStatusIs;
	}

	public String getProtectIfPageStatusIsNot() {
		return protectIfPageStatusIsNot;
	}

	public void setProtectIfPageStatusIsNot(String protectIfPageStatusIsNot) {
		this.protectIfPageStatusIsNot = protectIfPageStatusIsNot;
	}
	
	public String getRequired() {
		return required;
	}

	public void setRequired(String required) {
		this.required = required;
	}

	public String getDisableDojo() {
		return disableDojo;
	}

	public void setDisableDojo(String disableDojo) {
		this.disableDojo = disableDojo;
	}

	public String getForceEdit() {
		return forceEdit;
	}

	public void setForceEdit(String forceEdit) {
		this.forceEdit = forceEdit;
	}

	public boolean isFitContent() {
		return fitContent;
	}

	public void setFitContent(boolean fitContent) {
		this.fitContent = fitContent;
	}

	/**
	 * @return the useWysiwyg
	 */
	public String getUseWysiwyg() {
		return useWysiwyg;
	}

	/**
	 * @param useWysiwyg the useWysiwyg to set
	 */
	public void setUseWysiwyg(String useWysiwyg) {
		this.useWysiwyg = useWysiwyg;
	}

	/**
	 * @return the useCodeMirror
	 */
	public String getUseCodeMirror() {
		return useCodeMirror;
	}

	/**
	 * @param useCodeMirror the useCodeMirror to set
	 */
	public void setUseCodeMirror(String useCodeMirror) {
		this.useCodeMirror = useCodeMirror;
	}

	@Override
	protected int writeTagContent(TagWriter tagWriter) throws JspException {
		this.tagWriter = tagWriter;
		PageStatus pageStatus;
		try {
			pageStatus = TagUtils.getPageStatus(getNestedPath());
		} catch (javax.servlet.jsp.JspException e) {
			e.printStackTrace();
			throw new JspException(e);
		}
		if (pageStatus.isReadOnly()) {
			protectField();
		}
        if (protectIfPageStatusIs != null && pageStatus.equals(protectIfPageStatusIs)) {
            protectField();
        } else if (protectIfPageStatusIsNot != null && !pageStatus.equals(protectIfPageStatusIsNot)) {
            protectField();
        }
        checkMceSupport();
        checkCodeMirrorSupport();

		tagWriter.startTag("textarea");
		writeDefaultAttributes(tagWriter);
		writeOptionalAttribute(tagWriter, ROWS_ATTRIBUTE, getRows());
		writeOptionalAttribute(tagWriter, COLS_ATTRIBUTE, getCols());
		writeOptionalAttribute(tagWriter, ONSELECT_ATTRIBUTE, getOnselect());
		writeOptionalAttribute(tagWriter, MAXLENGTH_ATTRIBUTE, getMaxLengthAsString());
		String value = getDisplayString(getBoundValue(), getPropertyEditor());
		tagWriter.appendValue(processFieldValue(getName(), value, "textarea"));
		tagWriter.endTag();

		//super.writeTagContent(tagWriter);
		//String value = getDisplayString(getBoundValue(), getPropertyEditor());
		TagUtils.getSecuritySessionBean().setReadOnly(getName(), isReadonly(), value);
		return SKIP_BODY;
	}

	/**
	 * @throws JspException
	 */
	private void checkMceSupport() throws JspException {
		if ("true".equals(getUseWysiwyg())) {
        	if (isReadonly()) {
                setCssClass(getCssClass() + " mceReadonly");
        	} else {
                setCssClass(getCssClass() + " mceEditor");
        	}
        }
        //solo per readOnly.
        if ("onStartup".equals(getUseWysiwyg())) {
        	if (isReadonly()) 
                setCssClass(getCssClass() + " mceReadonly");
        }
        

        String editorMode = getEditorMode();
        if (getUseWysiwyg().startsWith("onDoubleClickSwitch")) {
        	String dblClick = "activateMce('" + resolveId() + "', '" + editorMode + "', undefined)";
        	setOndblclick(dblClick);
        }
	}

	/**
	 * @throws JspException
	 */
	private void checkCodeMirrorSupport() throws JspException {
		if ("true".equals(getUseCodeMirror())) {
			setDisableDojo("true");
			StringBuffer script = new StringBuffer();
			script.append("addCodeMirrorFor('" + resolveId() + "');");
			TagUtils.getCurrentForm(pageContext).addScript(script);
		}
	}

	private String getEditorMode() throws JspException {
		return (isReadonly() ? "read" : (getUseWysiwyg().endsWith("Small") ? "editSmall" : "edit"));
	}
	
	private void protectField() throws JspException {
		if (!ExpressionEvaluationUtils.evaluateBoolean("forceEdit", getForceEdit(), this.pageContext)) {
			setReadonly(true);
			setTabindex("-1");
		    if (getCssClass() == null || getCssClass().indexOf("protected") == -1) {
		        setCssClass(StringUtils.defaultString(getCssClass()) + " protected");
		    }
		}
	}

	@Override
	public int doEndTag() throws JspException {
		super.doEndTag();
		if (isLeftCharsIndicator()) {
			writeLeftCharsPart();
		}
		if (!ExpressionEvaluationUtils.evaluateBoolean("disableDojo", getDisableDojo(), this.pageContext) && !TagUtils.isBootstrapTheme()) {
			writeDojoScript(tagWriter);
		}
        if (getUseWysiwyg().startsWith("onButtonSwitch")) {
            String editorMode = getEditorMode();
        	tagWriter.startTag("button");
        	tagWriter.writeAttribute("onclick", "return activateMce('" + resolveId() + "', '" + editorMode + "', this);");
        	tagWriter.appendValue("Editor");
        	tagWriter.endTag();
        }
        if (getUseWysiwyg().equals("onStartup")){
        	tagWriter.startTag("script");
        	tagWriter.appendValue("activateMce('" + resolveId() + "', 'edit', undefined);");
        	tagWriter.endTag();

        }
        
        
        
		return EVAL_PAGE;
	}

	private void writeLeftCharsPart() throws JspException {
		tagWriter.startTag("div");
		tagWriter.writeAttribute("class", "leftChars");
		tagWriter.appendValue("caratteri rimanenti: ");
		tagWriter.startTag("span");
		tagWriter.writeAttribute("id", resolveId() + "_leftChars");
		tagWriter.endTag();
		tagWriter.endTag();
	}

	private void writeDojoScript(TagWriter tagWriter) throws JspException {
		StringBuffer script = new StringBuffer();
		script.append("Spring.addDecoration(new Spring.ElementDecoration({");
		script.append("elementId : '" + resolveId() + "',");
		if (isFitContent()) {
			script.append("widgetType : 'voila.form.ValidationTextarea',");
		} else {
			script.append("widgetType : 'voila.form.ValidationSimpleTextarea',");
		}
		script.append("widgetAttrs : {");
		script.append("required : " + ExpressionEvaluationUtils.evaluateBoolean("required", getRequired(), this.pageContext));
		script.append(",regExp : \"(.|\\\\s)*\"");
		if (getMaxLength() != null) {
			script.append(",maxLength : " + getMaxLength());
		}
		script.append("}}));");

		TagUtils.getCurrentForm(pageContext).addScript(script);
	}
	
	@Override
	public void doFinally() {
		setReadonly(false);
		setRequired("false");
		setTabindex(null);
		setCssClass(null);
		setDisabled(false);
		setFitContent(false);
		setRequired(null);
		setForceEdit(null);
		setDisableDojo(null);
		setProtectIfPageStatusIs(null);
		setProtectIfPageStatusIsNot(null);
		setMaxLength(null);
		setLeftCharsIndicator(false);
		setUseWysiwyg("false");
		super.doFinally();
	}

}
