package de.champonthis.buntspecht.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ResolvableType;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import de.champonthis.buntspecht.controller.support.EntityResponseStatusException;
import de.champonthis.buntspecht.security.LocalUserDetails;

@RestController
@RequestMapping("/auth")
public class AuthenticationController extends BaseController {

	private static String authorizationRequestBaseUri = "oauth2/authorization";

	@Autowired(required = false)
	private ClientRegistrationRepository clientRegistrationRepository;

	@GetMapping
	public Object me() {
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		if (auth != null && auth.getPrincipal() instanceof LocalUserDetails) {
			return (LocalUserDetails) auth.getPrincipal();
		}

		throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
	}

	@SuppressWarnings("unchecked")
	@GetMapping("external")
	public List<Client> getExternalLoginUrls() {
		List<Client> clients = new ArrayList<>();
		if (clientRegistrationRepository != null) {
			Iterable<ClientRegistration> clientRegistrations = null;
			ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository).as(Iterable.class);
			if (type != ResolvableType.NONE && ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) {
				clientRegistrations = (Iterable<ClientRegistration>) clientRegistrationRepository;
				clientRegistrations.forEach(registration -> clients.add(new Client(registration.getRegistrationId(),
						authorizationRequestBaseUri + "/" + registration.getRegistrationId())));
			}
		}

		return clients;
	}

	protected static class Client {

		private String id;

		private String loginUrl;

		public Client(String id, String loginUrl) {
			super();
			this.id = id;
			this.loginUrl = loginUrl;
		}

		public String getId() {
			return id;
		}

		public void setId(String id) {
			this.id = id;
		}

		public String getLoginUrl() {
			return loginUrl;
		}

		public void setLoginUrl(String loginUrl) {
			this.loginUrl = loginUrl;
		}

	}
}
