package info.bukova.isspst.validators;

import info.bukova.isspst.StringUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.bind.Property;
import org.zkoss.bind.ValidationContext;
import org.zkoss.bind.validator.AbstractValidator;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Messagebox;

public abstract class BaseValidator extends AbstractValidator
{
	private final static Logger log = LoggerFactory.getLogger(BaseValidator.class.getName());

	protected ValidationContext ctx;

	private HtmlBasedComponent htmlComponent;
	
	protected Logger getLogger()
	{
		return null;
	}

	public void errorMsg(ValidationContext ctx, String msg, String componentIdFocused)
	{
		this.addInvalidMessage(ctx, msg);

		Logger logger = this.getLogger();

		if (logger != null)
		{
			logger.error(msg);
		}

		htmlComponent = null;
		
		if ((componentIdFocused != null) && (!componentIdFocused.isEmpty()))
		{
			Component component = ctx.getBindContext().getComponent().getFellowIfAny(componentIdFocused, true);

			if ((component != null) && (component instanceof HtmlBasedComponent))
			{
				htmlComponent = (HtmlBasedComponent) component;
			}
		}
		
		Messagebox.show(msg, StringUtils.localize("Error"), Messagebox.OK, Messagebox.ERROR, new EventListener<Event>()
		{
			public void onEvent(Event evt) throws InterruptedException
			{
				if (htmlComponent != null)
				{
					htmlComponent.setFocus(true);
				}
			}
		});
	}

	public void addErrorMsg(ValidationContext ctx, String msg)
	{
		this.errorMsg(ctx, msg, null);
	}
	
	protected boolean validateIsNotNull(ValidationContext ctx, String property, String errMessage, String componentId)
	{
		Property prop = ctx.getProperties(property)[0];
		Object value = prop.getValue();

		if (value == null)
		{
			this.errorMsg(ctx, StringUtils.localize(errMessage), componentId);
			return false;
		}
		
		return true;
	}
	
	protected boolean validateIsNotNullOrNotEmpty(ValidationContext ctx, String property, String errMessage, String componentId)
	{
		Property prop = ctx.getProperties(property)[0];
		Object value = prop.getValue();

		if (value == null)
		{
			this.errorMsg(ctx, StringUtils.localize(errMessage), componentId);
			return false;
		}
		
		if ((value instanceof String) && ((String)value).isEmpty())
		{
			this.errorMsg(ctx, StringUtils.localize(errMessage), componentId);
			return false;
		}
		
		return true;
	}
	
	protected boolean validateRegExp(ValidationContext ctx, String property, String errMessage, String componentId, String regExpPattern) {
		String value = getStringValue(ctx, property);
		
		if (value != null && !value.isEmpty()) {
			Pattern pattern = Pattern.compile(regExpPattern); 
			Matcher matcher = pattern.matcher(value);
			
			if (!matcher.matches()) {
				errorMsg(ctx, StringUtils.localize(errMessage), componentId);
				return false;
			}
		}
		
		return true;
	}
	
	protected String getStringValue(ValidationContext ctx, String property) {
		Property prop = ctx.getProperties(property)[0];
		Object value = prop.getValue();
		
		if (value == null || !(value instanceof String)) {
			return null;
		}
		
		return (String)value;
	}

	protected String getStringProperty(String propertyName) {
		if (this.ctx == null) {
			log.warn("Neznámý ValidationContext!!!");
			return "";
		}

		if (StringUtils.isNullOrTrimmedEmpty(propertyName)) {
			log.warn("Chybné propertyName!!!");
			return "";
		}

		Property property = ctx.getProperties(propertyName)[0];

		if (property == null) {
			log.warn("Neexistující propertyName!!!");
			return "";
		}

		Object o = property.getValue();

		if (o instanceof String) {
			return (String) o;
		}
		else {
			log.warn("Chybný typ property '" + propertyName + "'!!!");
			return "";
		}
	}

	@Override
	public void validate(ValidationContext ctx) {
		this.ctx = ctx;
	}
}
