/**
 * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of the Liferay Enterprise
 * Subscription License ("License"). You may not use this file except in
 * compliance with the License. You can obtain a copy of the License by
 * contacting Liferay, Inc. See the License for the specific language governing
 * permissions and limitations under the License, including but not limited to
 * distribution rights of the Software.
 *
 *
 *
 */

package com.liferay.taglib.aui;

import com.liferay.portal.kernel.servlet.taglib.aui.ValidatorTag;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.TextFormatter;
import com.liferay.portal.kernel.util.Tuple;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.ModelHintsUtil;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.taglib.aui.base.BaseInputTag;

import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;

/**
 * @author Julio Camarero
 * @author Jorge Ferrer
 * @author Brian Wing Shun Chan
 */
public class InputTag extends BaseInputTag {

	@Override
	public int doEndTag() throws JspException {
		updateFormValidators();

		return super.doEndTag();
	}

	@Override
	public int doStartTag() throws JspException {
		addModelValidatorTags();

		if (getRequired()) {
			addRequiredValidatorTag();
		}

		return super.doStartTag();
	}

	public String getBaseType() {
		Class<?> model = getModel();

		String type = getType();

		String baseType = null;

		if ((model != null) && Validator.isNull(type)) {
			baseType = ModelHintsUtil.getType(model.getName(), getField());
		}
		else if (Validator.isNotNull(type)) {
			if (Validator.equals(type, "checkbox") ||
				Validator.equals(type, "radio") ||
				Validator.equals(type, "resource")) {

				baseType = type;
			}
		}

		if (Validator.isNull(baseType)) {
			baseType = "text";
		}

		return baseType;
	}

	@Override
	public String getField() {
		String field = super.getField();

		if (Validator.isNull(field)) {
			field = getName();
		}

		return field;
	}

	@Override
	public String getInputName() {
		String inputName = getName();

		Class<?> model = getModel();

		String type = getType();

		if ((model != null) && Validator.isNull(type)) {
			String fieldParam = getFieldParam();

			if (Validator.isNotNull(fieldParam)) {
				inputName = fieldParam;
			}
		}

		return inputName;
	}

	@Override
	public Class<?> getModel() {
		Class<?> model = super.getModel();

		if (model == null) {
			model = (Class<?>)pageContext.getAttribute(
				"aui:model-context:model");
		}

		return model;
	}

	protected void addModelValidatorTags() {
		Class<?> model = getModel();

		if ((model == null) || Validator.isNotNull(getType())) {
			return;
		}

		List<Tuple> modelValidators = ModelHintsUtil.getValidators(
			model.getName(), getField());

		if (modelValidators == null) {
			return;
		}

		for (Tuple modelValidator : modelValidators) {
			String validatorName = (String)modelValidator.getObject(1);
			String validatorErrorMessage = (String)modelValidator.getObject(2);
			String validatorValue = (String)modelValidator.getObject(3);
			boolean customValidator = (Boolean)modelValidator.getObject(4);
			boolean customValidatorRequired = (Boolean)modelValidator.getObject(
				5);

			ValidatorTag validatorTag = new ValidatorTagImpl(
				validatorName, validatorErrorMessage, validatorValue,
				customValidator, customValidatorRequired);

			addValidatorTag(validatorName, validatorTag);
		}
	}

	@Override
	protected boolean isCleanUpSetAttributes() {
		return _CLEAN_UP_SET_ATTRIBUTES;
	}

	@Override
	protected void setAttributes(HttpServletRequest request) {
		super.setAttributes(request);

		Object bean = getBean();

		if (bean == null) {
			bean = pageContext.getAttribute("aui:model-context:bean");
		}

		Class<?> model = getModel();

		String defaultLanguageId = getDefaultLanguageId();

		if (Validator.isNull(defaultLanguageId)) {
			defaultLanguageId = (String)pageContext.getAttribute(
				"aui:model-context:defaultLanguageId");
		}

		if (Validator.isNull(defaultLanguageId)) {
			if ((model != null) &&
				ModelHintsUtil.hasField(model.getName(), "groupId")) {

				ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
					WebKeys.THEME_DISPLAY);

				defaultLanguageId = LocaleUtil.toLanguageId(
					themeDisplay.getSiteDefaultLocale());
			}
		}

		if (Validator.isNull(defaultLanguageId)) {
			Locale defaultLocale = LocaleUtil.getDefault();

			defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
		}

		String name = getName();

		int pos = name.indexOf(StringPool.DOUBLE_DASH);

		if (pos != -1) {
			name = name.substring(pos + 2, name.length() - 2);
		}

		String field = getField();

		if (Validator.isNull(field)) {
			field = getName();
		}

		String formName = getFormName();

		if (formName == null) {
			FormTag formTag = (FormTag)findAncestorWithClass(
				this, FormTag.class);

			if (formTag != null) {
				formName = formTag.getName();
			}
		}

		String id = getId();
		String type = getType();

		if (Validator.isNull(id)) {
			String fieldParam = getFieldParam();

			if ((model != null) && Validator.isNull(type) &&
				Validator.isNotNull(fieldParam)) {

				id = fieldParam;
			}
			else if (!Validator.equals(type, "assetTags") &&
					 !Validator.equals(type, "radio")) {

				id = name;
			}
			else {
				id = StringUtil.randomId();
			}
		}

		String label = getLabel();

		if (label == null) {
			label = TextFormatter.format(name, TextFormatter.P);
		}

		String title = getTitle();

		if ((title == null) && (Validator.isNull(label) ||
			 Validator.equals(type, "image"))) {

			title = TextFormatter.format(name, TextFormatter.P);
		}

		String forLabel = id;

		if (Validator.equals(type,"assetTags")) {
			forLabel = forLabel.concat("assetTagNames");
		}
		else if (Validator.equals(type, "checkbox")) {
			forLabel = forLabel.concat("Checkbox");
		}

		String languageId = getLanguageId();

		if (Validator.isNotNull(languageId)) {
			forLabel = forLabel + StringPool.UNDERLINE + languageId;
		}

		boolean wrappedField = getWrappedField();

		FieldWrapperTag fieldWrapper = (FieldWrapperTag)findAncestorWithClass(
			this, FieldWrapperTag.class);

		if (fieldWrapper != null) {
			wrappedField = true;
		}

		setNamespacedAttribute(request, "baseType", getBaseType());
		setNamespacedAttribute(request, "bean", bean);
		setNamespacedAttribute(request, "defaultLanguageId", defaultLanguageId);
		setNamespacedAttribute(request, "field", field);
		setNamespacedAttribute(request, "forLabel", forLabel);
		setNamespacedAttribute(request, "formName", formName);
		setNamespacedAttribute(request, "id", id);
		setNamespacedAttribute(request, "label", label);
		setNamespacedAttribute(request, "model", model);
		setNamespacedAttribute(request, "title", String.valueOf(title));
		setNamespacedAttribute(request, "wrappedField", wrappedField);

		request.setAttribute(getAttributeNamespace() + "value", getValue());

		Map<String, ValidatorTag> validatorTags = getValidatorTags();

		if ((validatorTags != null) &&
			(validatorTags.get("required") != null)) {

			setNamespacedAttribute(
				request, "required", Boolean.TRUE.toString());
		}
	}

	protected void updateFormValidators() {
		List<ValidatorTag> validatorTags = ListUtil.fromMapValues(
			getValidatorTags());

		if (validatorTags == null) {
			return;
		}

		HttpServletRequest request =
			(HttpServletRequest)pageContext.getRequest();

		Map<String, List<ValidatorTag>> validatorTagsMap =
			(Map<String, List<ValidatorTag>>)request.getAttribute(
				"aui:form:validatorTagsMap");

		if (validatorTagsMap != null) {
			String inputName = getInputName();

			if (Validator.equals(getType(), "checkbox")) {
				inputName = inputName.concat("Checkbox");
			}

			String languageId = getLanguageId();

			if (Validator.isNotNull(languageId)) {
				inputName = inputName + StringPool.UNDERLINE + languageId;
			}

			validatorTagsMap.put(inputName, validatorTags);
		}
	}

	private static final boolean _CLEAN_UP_SET_ATTRIBUTES = true;

}