package eu.dnetlib.data.utility.cleaner.inspector;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.google.common.collect.Lists;

import eu.dnetlib.data.utility.cleaner.CleaningRule;
import eu.dnetlib.data.utility.cleaner.CleaningRuleFactory;
import eu.dnetlib.data.utility.cleaner.rmi.CleanerException;
import eu.dnetlib.enabling.inspector.AbstractInspectorController;
import eu.dnetlib.miscutils.collections.MappedCollection;
import eu.dnetlib.miscutils.functional.UnaryFunction;

@Controller
public class CleanerInspector extends AbstractInspectorController {

	@Resource
	private CleaningRuleFactory cleaningRuleFactory;

	public static class SelectOption {

		private String value;
		private boolean selected;

		public SelectOption(final String value, final boolean selected) {
			super();
			this.value = value;
			this.selected = selected;
		}

		public String getValue() {
			return value;
		}

		public void setValue(final String value) {
			this.value = value;
		}

		public boolean isSelected() {
			return selected;
		}

		public void setSelected(final boolean selected) {
			this.selected = selected;
		}
	}

	@RequestMapping(value = "/inspector/cleaner.do")
	public void cleaner(final Model model,
			@RequestParam(value = "rule", required = false) final String ruleId,
			@RequestParam(value = "dirtyText", required = false) final String dirtyText) throws CleanerException {

		List<String> rules = Lists.newArrayList(cleaningRuleFactory.getRuleIds());
		model.addAttribute("rules", selectOptions(rules, ruleId));

		if ((ruleId != null) && (dirtyText != null)) {
			CleaningRule rule = cleaningRuleFactory.obtainCleaningRule(ruleId);
			model.addAttribute("dirtyText", dirtyText);
			model.addAttribute("cleanedText", rule.evaluate(dirtyText));
		}
	}

	/**
	 * Given an list of values, return a list of SelectOption instances which have the "selected" boolean field set to true only for the
	 * element matching "current".
	 * 
	 * @param input
	 *            list of input strings
	 * @param current
	 *            current value to select
	 * @return
	 */
	private List<SelectOption> selectOptions(final List<String> input, final String current) {
		final UnaryFunction<SelectOption, String> mapper = new UnaryFunction<SelectOption, String>() {

			@Override
			public SelectOption evaluate(final String value) {
				return new SelectOption(value, value.equals(current));
			}
		};
		return Lists.newArrayList(new MappedCollection<SelectOption, String>(input, mapper));
	}

}
