package eu.dnetlib.lbs.controllers;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Predicate;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import eu.dnetlib.lbs.LiteratureBrokerServiceConfiguration;
import eu.dnetlib.lbs.topics.TopicType;
import eu.dnetlib.lbs.topics.TopicTypeRepository;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@RestController
@RequestMapping("/api/topic-types")
@Api(tags = LiteratureBrokerServiceConfiguration.TAG_TOPIC_TYPES)
public class TopicsController extends AbstractLbsController {

	@Autowired
	private TopicTypeRepository topicTypeRepo;

	private final Predicate<String> verifyExpression =
			Pattern.compile("^([a-zA-Z0-9._-]+|<[a-zA-Z0-9._-]+>)(\\/([a-zA-Z0-9._-]+|<[a-zA-Z0-9._-]+>))+$").asPredicate();

	@ApiOperation("Return the list of topic types")
	@RequestMapping(value = "", method = RequestMethod.GET)
	public Iterable<TopicType> listTopicTypes() {
		return this.topicTypeRepo.findAll();
	}

	@ApiOperation("Register a new topic type")
	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public TopicType registerTopicType(
			@RequestParam(name = "name", required = true) final String name,
			@RequestParam(name = "expression", required = true) final String expression,
			@RequestParam(name = "producerId", required = true) final String producerId,
			@RequestParam(name = "mapKeys", required = true) final String mapKeys) {

		if (StringUtils.isBlank(name)) { throw new IllegalArgumentException("name is empty"); }
		if (StringUtils.isBlank(expression)) { throw new IllegalArgumentException("expression is empty"); }
		if (!this.verifyExpression.test(expression)) { throw new IllegalArgumentException("Invalid expression: " + expression); }

		final String id = "tt-" + UUID.randomUUID();
		final TopicType type = new TopicType(id, name, expression, producerId, mapKeys);

		this.topicTypeRepo.save(type);

		return type;
	}

	@ApiOperation("Return a topic type by ID")
	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
	public TopicType getTopicType(@PathVariable final String id) {
		return this.topicTypeRepo.findById(id).get();
	}

	@ApiOperation("Delete a topic type by ID")
	@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
	public List<String> deleteTopicType(@PathVariable final String id) {
		this.topicTypeRepo.deleteById(id);
		return Arrays.asList("Done.");
	}

	@ApiOperation("Delete all topic types")
	@RequestMapping(value = "", method = RequestMethod.DELETE)
	public Map<String, Object> clearTopicTypes() {
		final Map<String, Object> res = new HashMap<>();
		this.topicTypeRepo.deleteAll();
		res.put("deleted", "all");
		return res;
	}
}
