/*
 * Licensed under MIT (https://github.com/ligoj/ligoj/blob/master/LICENSE)
 */
package org.ligoj.bootstrap.resource.system.user;

import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.transaction.Transactional;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.ligoj.bootstrap.dao.system.SystemUserSettingRepository;
import org.ligoj.bootstrap.model.system.AbstractNamedValue;
import org.ligoj.bootstrap.model.system.SystemUserSetting;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

/**
 * Manage {@link SystemUserSetting}. User settings are scoped by current user.
 */
@Service
@Path("/system/setting")
@Transactional
@Produces(MediaType.APPLICATION_JSON)
public class UserSettingResource {

	@Autowired
	private SystemUserSettingRepository repository;

	/**
	 * Delete a {@link SystemUserSetting}
	 * 
	 * @param name
	 *            the user setting name to delete.
	 */
	@DELETE
	@Path("{name}")
	public void delete(@PathParam("name") final String name) {
		repository.delete(SecurityContextHolder.getContext().getAuthentication().getName(), name);
	}

	/**
	 * Return all user's settings.
	 * 
	 * @return all user's settings.
	 */
	@GET
	public Map<String, Object> findAll() {
		return findAll(SecurityContextHolder.getContext().getAuthentication().getName());
	}

	/**
	 * Return all settings of given user.
	 * 
	 * @param login
	 *            USer login to check.
	 * @return all user's settings.
	 */
	public Map<String, Object> findAll(final String login) {
		return repository.findByLogin(login).stream()
				.collect(Collectors.toMap(AbstractNamedValue::getName, AbstractNamedValue::getValue));
	}

	/**
	 * Return a specific setting of current user.
	 * 
	 * @param name
	 *            The setting's name.
	 * @return a specific user's setting. May be <code>null</code>
	 */
	@GET
	@Path("{name}")
	public Object findByName(final String name) {
		return findByName(SecurityContextHolder.getContext().getAuthentication().getName(), name);
	}

	/**
	 * Return a specific user's setting.
	 * 
	 * @param login
	 *            the user login owning the setting.
	 * @param name
	 *            The setting's name.
	 * @return a specific user's setting. May be <code>null</code>.
	 */
	public String findByName(final String login, final String name) {
		return Optional.ofNullable(repository.findByLoginAndName(login, name)).map(SystemUserSetting::getValue)
				.orElse(null);
	}

	/**
	 * Save or update a setting and return the corresponding identifier.
	 * 
	 * @param name
	 *            the setting name.
	 * @param value
	 *            the new value.
	 */
	@POST
	@PUT
	@Path("{name}/{value}")
	public void saveOrUpdate(@PathParam("name") final String name, @PathParam("value") final String value) {
		final var user = SecurityContextHolder.getContext().getAuthentication().getName();
		final var setting = repository.findByLoginAndName(user, name);
		if (setting == null) {
			final var entity = new SystemUserSetting();
			entity.setLogin(user);
			entity.setName(name);
			entity.setValue(value);
			repository.saveAndFlush(entity);
		} else {
			setting.setValue(value);
		}
	}

}

@@ -1173,39 +1173,24 @@
  @param name
-%0A%09 *           
  the user se
@@ -1678,31 +1678,16 @@
 am login
-%0A%09 *           
  USer lo
@@ -2007,39 +2007,24 @@
  @param name
-%0A%09 *           
  The setting
@@ -2332,31 +2332,16 @@
 am login
-%0A%09 *           
  the use
@@ -2383,30 +2383,16 @@
 ram name
-%0A%09 *          
   The se
@@ -2709,83 +2709,85 @@
 ing 
-and return the corresponding identifier.%0A%09 * %0A%09 * @param
+of a given user.%0A%09 * %0A%09 * @param user  the related user
  name
+.
 %0A%09 * 
-         
+@param name
   th
@@ -2822,23 +2822,8 @@
 alue
-%0A%09 *           
  the
@@ -2856,24 +2856,53 @@
 PUT%0A%09@Path(%22
+/system/admin-setting/%7Buser%7D/
 %7Bname%7D/%7Bvalu
@@ -2964,20 +2964,20 @@
  String 
-name
+user
 , @PathP
@@ -2982,20 +2982,19 @@
 hParam(%22
-valu
+nam
 e%22) fina
@@ -3006,101 +3006,58 @@
 ing 
+name,%0A%09%09%09@PathParam(%22
 value
+%22
 ) 
-%7B%0A%09%09
 final 
-var user = SecurityContextHolder.getContext().getAuthentication().getName();
+String value) %7B
 %0A%09%09f
@@ -3351,10 +3351,412 @@
 %09%09%7D%0A%09%7D%0A%0A
+%09/**%0A%09 * Save or update a setting of current given user.%0A%09 * %0A%09 * @param name  the setting name.%0A%09 * @param value the new value.%0A%09 */%0A%09@POST%0A%09@PUT%0A%09@Path(%22%7Bname%7D/%7Bvalue%7D%22)%0A%09public void saveOrUpdate(@PathParam(%22name%22) final String name, @PathParam(%22value%22) final String value) %7B%0A%09%09final var user = SecurityContextHolder.getContext().getAuthentication().getName();%0A%09%09saveOrUpdate(user, name, value);%0A%09%7D%0A%0A
 %7D%0A

Add admin setting API