package com.libreecm.db.controllers;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.chemistry.opencmis.commons.data.AclCapabilities;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.libreecm.commonAPI.auxiliars.exceptions.*;
import com.libreecm.commonAPI.configuration.ComponentConfig;
import com.libreecm.db.jpa.CmisExtensionElementImpl;
import com.libreecm.db.jpa.CreatablePropertyTypesImpl;
import com.libreecm.db.jpa.NewTypeSettableAttributesImpl;
import com.libreecm.db.jpa.ObjectType;
//import com.libreecm.db.jpa.PropertyDefinition;
import com.libreecm.db.jpa.Repository;
import com.libreecm.db.jpa.RepositoryCapabilitiesImpl;
//import com.libreecm.db.jpa.properties.Properties;
//import com.libreecm.db.jpa.properties.repositories.*;
import com.libreecm.db.jpa.repositories.*;
import com.libreecm.db.jpa.users.AclCapabilitiesImpl;
import com.libreecm.db.jpa.users.repositories.AclCapabilitiesRepository;

@RestController
public class RepositoryController extends BaseController {
 
	private final CmisExtensionElementRepository extensionRepository;
	private final RepositoryRepository repositoryRepository;
	private final RepositoryCapabilityRepository repositoryCapabilitiesRepository;
	private final AclCapabilitiesRepository capabilitiesRepository;
	private final CreatablePropertyTypesRepository creatablePropertyTypesRepository;
	private final NewTypeSettableAttributesRepository newTypeSettableAttributesRepository;
	private final ObjectTypeRepository objectTypeRepository;

	@Autowired
	RepositoryController(RepositoryRepository repositoryRepository, CmisExtensionElementRepository extensionRepository,
			AclCapabilitiesRepository capabilitiesRepository,
			RepositoryCapabilityRepository repositoryCapabilitiesRepository,
			CreatablePropertyTypesRepository creatablePropertyTypesRepository,
			NewTypeSettableAttributesRepository newTypeSettableAttributesRepository,
			ObjectTypeRepository objectTypeRepository
	) {
		this.objectTypeRepository = objectTypeRepository;
		// this.propertyDefinitionRepository=propertyDefinitionRepository;
		this.repositoryRepository = repositoryRepository;
		this.extensionRepository = extensionRepository;
		this.capabilitiesRepository = capabilitiesRepository;
		this.repositoryCapabilitiesRepository = repositoryCapabilitiesRepository;
		this.creatablePropertyTypesRepository = creatablePropertyTypesRepository;
		this.newTypeSettableAttributesRepository = newTypeSettableAttributesRepository;
	
	}

	/**
	 * Returns a Repository from the DDBB by it's name
	 * 
	 * @param name
	 * @return
	 */
	@RequestMapping(value = "/repository", method = RequestMethod.GET)
	public @ResponseBody Repository repository(@RequestParam(value = "name", required = true) String name) {
		// validateUser();
		Repository repository = repositoryRepository.findByName(name)
				.orElseThrow(() -> new RepositoryNotFoundException(name));
				return repository;
	}

	/**
	 * Returns a Repository from the DDBB by it's id
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/repositorybyid", method = RequestMethod.GET)
	public @ResponseBody Repository repositoryById(@RequestParam(value = "id", required = true) String id) {
		// validateUser();
		Repository repository =null;
		repository = repositoryRepository.findById(Integer.parseInt(id)).orElseThrow(() ->new RepositoryNotFoundException(id));
		
		
		return repository;
	}

	/**
	 * A class that returns a RepositoryCapabilities from the DDBB
	 * 
	 * @param id
	 * @return
	 * @throws NotFoundRepositoryCapabilitiesException
	 * @throws NumberFormatException
	 */
	@RequestMapping(value = "/repositoryCapabilities", method = RequestMethod.GET)
	public @ResponseBody RepositoryCapabilitiesImpl repositoryCapabilities(
			@RequestParam(value = "id", required = true) String id)
					throws NumberFormatException, NotFoundRepositoryCapabilitiesException {
		// validateUser();
		RepositoryCapabilitiesImpl repositoryCapabilities = repositoryCapabilitiesRepository
				.findById(Integer.parseInt(id)).orElseThrow(() -> new NotFoundRepositoryCapabilitiesException(id));
		return repositoryCapabilities;
	}

	@RequestMapping(value = "/repositories", method = RequestMethod.GET)
	public @ResponseBody Collection<Repository> repositories() {
		// validateUser();
		List<Repository> result = this.repositoryRepository.findAll();
		if (result.size() == 0) {
			return new ArrayList<>();
		}
		return result;
	}

	@RequestMapping(value = "/typechildren", method = RequestMethod.GET)
	public @ResponseBody Collection<ObjectType> getTypeChildren(
			@RequestParam(value = "repositoryName", required = true) String repositoryName,
			@RequestParam(value = "typeid", required = true) String typeId) {
		// validateUser();
		List<ObjectType> result = this.objectTypeRepository.findByParentTypeIdAndRepositoryName(typeId, repositoryName);

		return result;
	}

	@RequestMapping(value = "/extension", method = RequestMethod.POST)
	/**
	 * A class that saves a CmisExtensionElement to the DDBB
	 * 
	 * @param CmisExtensionElement
	 * @return
	 */
	public @ResponseBody CmisExtensionElementImpl cmisExtensionElement(@RequestBody CmisExtensionElementImpl extension)
			throws AlreadyExistingExtensionException {
		// validateUser();
		if (this.extensionRepository.findById(Integer.parseInt(extension.getId())).isPresent()) {
			throw new AlreadyExistingExtensionException(extension.getId());
		}
		extension = extensionRepository.save(extension);
		// throw new AddRepositoryOkException(repository.getId());
		return extension;
	}

	@RequestMapping(value = "/aclCapabilities", method = RequestMethod.POST)
	/**
	 * A class that saves AclCapabilities to the DDBB
	 * 
	 * @param aclCapabilities
	 * @return
	 */
	public @ResponseBody AclCapabilities aclCapabilities(@RequestBody AclCapabilitiesImpl capabilities)
			throws AlreadyExistingAclCapabilitiesException {
		// validateUser();
		if (this.capabilitiesRepository.findById(capabilities.getId()).isPresent()) {
			throw new AlreadyExistingAclCapabilitiesException(capabilities.getId());
		}
		capabilities = capabilitiesRepository.save(capabilities);
		// throw new AddRepositoryOkException(repository.getId());
		return capabilities;
	}
	
	@RequestMapping(value = "/repositoryCapabilities", method = RequestMethod.POST)
	/**
	 * A class that saves a RepositoryCapability the DDBB
	 * 
	 * @param repositoryCapability
	 * @return
	 */
	public @ResponseBody RepositoryCapabilitiesImpl repositoryCapabilities(
			@RequestBody RepositoryCapabilitiesImpl capabilities)
					throws AlreadyExistingRepositoryCapabilitiesException {
		// validateUser();
		if (this.repositoryCapabilitiesRepository.findById(Integer.parseInt(capabilities.getId())).isPresent()) {
			throw new AlreadyExistingRepositoryCapabilitiesException(capabilities.getId());
		}
		capabilities = repositoryCapabilitiesRepository.save(capabilities);
		// throw new AddRepositoryOkException(repository.getId());
		return capabilities;
	}

	@RequestMapping(value = "/repository", method = RequestMethod.POST)
	/**
	 * A class that saves a Repository to the DDBB If the repository exists,
	 * it's overridden
	 * 
	 * @param repository
	 * @return
	 */
	public @ResponseBody Repository repository(@RequestBody Repository repository) {
		// validateUser();
		repository = repositoryRepository.saveAndFlush(repository);
		
		return repository;
	}

	@RequestMapping(value = "/creatableProperty", method = RequestMethod.POST)
	/**
	 * A class that saves a CreatablePropertyTypes to the DDBB
	 * 
	 * @param creatablePropertyTypes
	 * @return
	 */
	public @ResponseBody CreatablePropertyTypesImpl creatablePropertyTypes(
			@RequestBody CreatablePropertyTypesImpl creatablePropertyTypes)
					throws AlreadyExistingCreatablePropertyTypesException {
		// validateUser();
		if (this.creatablePropertyTypesRepository.findById(Integer.parseInt(creatablePropertyTypes.getId()))
				.isPresent()) {
			throw new AlreadyExistingCreatablePropertyTypesException(creatablePropertyTypes.getId());
		}
		creatablePropertyTypes = creatablePropertyTypesRepository.save(creatablePropertyTypes);
		return creatablePropertyTypes;
	}

	@RequestMapping(value = "/newTypeSettableAttributes", method = RequestMethod.POST)
	/**
	 * A class that saves a NewTypeSettableAttributes to the DDBB
	 * 
	 * @param newTypeSettableAttributes
	 * @return
	 */
	public @ResponseBody NewTypeSettableAttributesImpl newTypeSettableAttributes(
			@RequestBody NewTypeSettableAttributesImpl newTypeSettableAttributes)
					throws AlreadyExistingNewTypeSettableAttributesException {
		// validateUser();
		if (this.newTypeSettableAttributesRepository
				.findById(Integer.parseInt(newTypeSettableAttributes.getId())) != null) {
			throw new AlreadyExistingNewTypeSettableAttributesException(newTypeSettableAttributes.getId());
		}
		newTypeSettableAttributes = newTypeSettableAttributesRepository.save(newTypeSettableAttributes);
		// throw new AddRepositoryOkException(repository.getId());
		return newTypeSettableAttributes;
	}

	@RequestMapping(value = "/newTypeSettableAttributes", method = RequestMethod.GET)
	/**
	 * A class that gets a NewTypeSettableAttributes from the DDBB
	 * 
	 * @param newTypeSettableAttributesId
	 * @param Id
	 * @return
	 */
	public @ResponseBody NewTypeSettableAttributesImpl getNewTypeSettableAttributes(
			@RequestParam(value = "id", required = true) String id) {
		// validateUser();
		return this.newTypeSettableAttributesRepository.findById(Integer.parseInt(id));
	}

}
