package org.gcube.accounting.datamodel.validations.validators;

import java.io.Serializable;
import java.util.List;

import org.gcube.accounting.aggregator.RegexRulesAggregator;
import org.gcube.accounting.datamodel.basetypes.AbstractServiceUsageRecord;
import org.gcube.documentstore.exception.InvalidValueException;
import org.gcube.documentstore.records.Record;
import org.gcube.documentstore.records.implementation.FieldAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Luca Frosini (ISTI - CNR)
 */
public class Harmonizer implements FieldAction {
	
	private static Logger logger = LoggerFactory.getLogger(Harmonizer.class);
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public Serializable validate(String key, Serializable value, Record record) throws InvalidValueException {
		
		if(!(record instanceof AbstractServiceUsageRecord)) {
			throw new RuntimeException(record.toString() + "is not an instace of " + AbstractServiceUsageRecord.class.getSimpleName());
		}
		
		if(!(value instanceof String)) {
			throw new InvalidValueException(value.toString() + "is not a " + String.class.getSimpleName());
		}
		
		AbstractServiceUsageRecord serviceUsageRecord = (AbstractServiceUsageRecord) record;
		
		String serviceClass = serviceUsageRecord.getServiceClass();
		if(serviceClass==null) {
			logger.debug("{} is not already set. The check will be postponed to validation phase", AbstractServiceUsageRecord.SERVICE_CLASS);
			return value;
		}
		
		String serviceName = serviceUsageRecord.getServiceName();
		if(serviceName==null) {
			logger.debug("{} is not already set. The check will be postponed to validation phase", AbstractServiceUsageRecord.SERVICE_NAME);
			return value;
		}
		
		List<MatcherReplace> matcherReplaceList = RegexRulesAggregator.getInstance().getMatcherReplaceList();
		
		String calledMethod = (String) value;
		
		for(MatcherReplace matcherReplace : matcherReplaceList) {
			Replace replace = matcherReplace.check(serviceClass, serviceName, calledMethod);
			if(replace != null) {
				serviceClass = replace.getServiceClass();
				serviceName = replace.getServiceName();
				calledMethod = replace.getCalledMethod();
			}
		}
		
		serviceUsageRecord.setServiceClass(serviceClass);
		serviceUsageRecord.setServiceName(serviceName);
		
		return calledMethod;
	}

}
