package eu.eudat.logic.security.customproviders.LinkedIn;

import eu.eudat.logic.security.validators.linkedin.helpers.LinkedInResponseToken;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

@Component("LinkedInCustomProvider")
public class LinkedInCustomProviderImpl implements LinkedInCustomProvider {

	private Environment environment;

	public LinkedInCustomProviderImpl(Environment environment) {
		this.environment = environment;
	}

	public LinkedInUser getUser(String accessToken) {
		RestTemplate restTemplate = new RestTemplate();
		HttpHeaders headers = this.createBearerAuthHeaders(accessToken);
		HttpEntity<String> entity = new HttpEntity<>(headers);

		Map profileValues = restTemplate.exchange(this.environment.getProperty("linkedin.login.user_info_url"), HttpMethod.GET, entity, Map.class).getBody();
		Map emailValues = restTemplate.exchange(this.environment.getProperty("linkedin.login.user_email"), HttpMethod.GET, entity, Map.class).getBody();
		LinkedInUser linkedInUser = new LinkedInUser();
		linkedInUser.setEmail((String)emailValues.get("email"));
		linkedInUser.setName((String)profileValues.get("localizedFirstName"));
		linkedInUser.setId((String)profileValues.get("id"));
		return linkedInUser;
	}

	public LinkedInResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret) {
		RestTemplate template = new RestTemplate();
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

		MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();

		map.add("grant_type", "authorization_code");
		map.add("code", code);
		map.add("redirect_uri", redirectUri);
		map.add("client_id", clientId);
		map.add("client_secret", clientSecret);
		HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);

		Map<String, Object> values = template.postForObject(this.environment.getProperty("linkedin.login.access_token_url"), request, Map.class);
		LinkedInResponseToken linkedInResponseToken = new LinkedInResponseToken();
		linkedInResponseToken.setAccessToken((String) values.get("access_token"));
		linkedInResponseToken.setExpiresIn((Integer) values.get("expires_in"));

		return linkedInResponseToken;
	}

	private HttpHeaders createBearerAuthHeaders(String accessToken) {
		return new HttpHeaders() {{
			String authHeader = "Bearer " + new String(accessToken);
			set("Authorization", authHeader);
		}};
	}
}
