package eu.dnetlib.msro.workflows.nodes.is;

import java.io.StringReader;
import java.util.List;

import javax.annotation.Resource;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.sarasvati.Arc;
import com.googlecode.sarasvati.NodeToken;

import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
import eu.dnetlib.msro.rmi.MSROException;
import eu.dnetlib.msro.workflows.nodes.ProgressJobNode;
import eu.dnetlib.msro.workflows.nodes.SimpleJobNode;
import eu.dnetlib.msro.workflows.util.ProgressProvider;
import eu.dnetlib.msro.workflows.util.WorkflowsConstants;

public class ValidateProfilesJobNode extends SimpleJobNode implements ProgressJobNode {

	@Resource
	private UniqueServiceLocator serviceLocator;

	private int total = 0;
	private int current = 0;

	private static final Log log = LogFactory.getLog(ValidateProfilesJobNode.class);

	@Override
	protected String execute(final NodeToken token) throws Exception {

		final ISLookUpService lookup = serviceLocator.getService(ISLookUpService.class);
		final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

		int invalidTotals = 0;

		final List<String> list = lookup.listResourceTypes();

		this.total = list.size();
		this.current = 0;
		for (String resourceType : list) {
			int valid = 0;
			int invalid = 0;

			final String schemaSource = lookup.getResourceTypeSchema(resourceType);
			final Schema schema = schemaFactory.newSchema(new StreamSource(new StringReader(schemaSource)));
			final Validator validator = schema.newValidator();

			for (String profile : lookup.quickSearchProfile("/RESOURCE_PROFILE[./HEADER/RESOURCE_TYPE/@value='" + resourceType + "']")) {
				try {
					validator.validate(new StreamSource(new StringReader(profile)));
					valid++;
				} catch (Exception e) {
					invalid++;
				}
			}
			invalidTotals += invalid;

			final String message = String.format("Valid: %s, Invalid: %s, Total: %s", valid, invalid, valid + invalid);
			token.getEnv().setAttribute(WorkflowsConstants.MAIN_LOG_PREFIX + resourceType, message);
			log.info("Validation of " + resourceType + " profiles: " + message);
		}

		if (invalidTotals > 0) { throw new MSROException("Validation wf has found " + invalidTotals + " invalid profiles"); }

		return Arc.DEFAULT_ARC;
	}

	@Override
	public ProgressProvider getProgressProvider() {
		return new ProgressProvider() {

			@Override
			public boolean isInaccurate() {
				return false;
			}

			@Override
			public int getTotalValue() {
				return total;
			}

			@Override
			public int getCurrentValue() {
				return current;
			}
		};
	}

}
