package gp.e3.autheo.client.internal.token;

import gp.e3.autheo.client.dtos.TokenDTO;
import gp.e3.autheo.client.exceptions.InvalidStateException;
import gp.e3.autheo.client.utils.HttpUtils;

import java.io.IOException;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import com.google.gson.Gson;

public class TokenHandler {

	private enum TokenHandlerSingleton {

		INSTANCE;

		public static final String NIL = "nil";
		// public static final String OK = "OK";

		private Gson gson;
		private JedisPool redisPool;

		private boolean singletonHasBeenInitialized() {

			return (gson != null) && (redisPool != null);
		}

		public void initializeSingleton(Gson gson, JedisPool jedisPool) {

			if (!singletonHasBeenInitialized()) {
				
				this.gson = gson;
				redisPool = jedisPool;
			}
		}
		
		public TokenDTO getTokenDTOFromStringAsJSON(String stringAsJSON) {
			
			return gson.fromJson(stringAsJSON, TokenDTO.class);
		}

		public TokenDTO getModuleTokenFromRedis(String sellerId) throws InvalidStateException {

			TokenDTO tokenDTO = null;

			if (singletonHasBeenInitialized()) {

				Jedis redisClient = redisPool.getResource();
				String tokenToString = redisClient.get(sellerId);
				redisPool.returnResource(redisClient);

				if (!StringUtils.isBlank(tokenToString) && !tokenToString.equalsIgnoreCase(NIL)) {
					tokenDTO = TokenDTO.buildTokenDTOFromTokenToString(tokenToString);
				}

			} else {

				String errorMessage = "The singleton has not been initialized by first time.";
				throw new InvalidStateException(errorMessage);
			}

			return tokenDTO;
		}
	}

	public TokenHandler(Gson gson, JedisPool jedisPool) {
		
		TokenHandlerSingleton.INSTANCE.initializeSingleton(gson, jedisPool);
	}

	private TokenDTO getOrganizationModuleTokenFromAutheo(String organizationId) {
		
		TokenDTO moduleTokenDTO = null;
		
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse httpResponse = null;
		
		try {
			
			String uri = "http://localhost:9002/api/organizations/" + organizationId + "/module-token";
			HttpGet getRequest = new HttpGet(uri);
			
			String appJson = ContentType.APPLICATION_JSON.toString();
			getRequest.addHeader("Accept", appJson);
			getRequest.addHeader("Content-Type", appJson + "; charset=UTF-8");
			
			httpClient = HttpClientBuilder.create().build();
			httpResponse = httpClient.execute(getRequest);
			
			if (httpResponse.getStatusLine().getStatusCode() == 200) {
				
				String httpEntityAsString = HttpUtils.getHttpEntityAsString(httpResponse.getEntity());
				moduleTokenDTO = TokenHandlerSingleton.INSTANCE.getTokenDTOFromStringAsJSON(httpEntityAsString);
			}
			
		} catch (IOException e) {
			
			e.printStackTrace();
			
		} finally {
			
			try {
				httpClient.close();
				httpResponse.close();
			} catch (IOException e) {
				
				e.printStackTrace();
			}
		}
		
		return moduleTokenDTO;
	}
	
	public TokenDTO getModuleTokenFromRedis(String sellerId) throws InvalidStateException {
		
		TokenDTO moduleToken = TokenHandlerSingleton.INSTANCE.getModuleTokenFromRedis(sellerId);
		
		if (moduleToken == null) {
			
			moduleToken = getOrganizationModuleTokenFromAutheo(sellerId);
		}
		
		return moduleToken;
	}
}
@@ -748,16 +748,71 @@
  %22nil%22;%0A
+%09%09public static final String SUPER_USER = %22superuser%22;%0A
 %09%09// pub
@@ -3572,9 +3572,399 @@
 ken;%0A%09%7D%0A
+%09%0A%09public TokenDTO getSuperUserTokenFromRedis() throws InvalidStateException %7B%0A%09%09%0A%09%09String superUserValue = TokenHandlerSingleton.SUPER_USER;%0A%09%09TokenDTO superUserToken = TokenHandlerSingleton.INSTANCE.getModuleTokenFromRedis(superUserValue);%0A%09%09%0A%09%09if (superUserToken == null) %7B%0A%09%09%09%0A%09%09%09superUserToken = getOrganizationModuleTokenFromAutheo(superUserValue);%0A%09%09%7D%0A%09%09%0A%09%09return superUserToken;%0A%09%7D%0A
 %7D

Add super user support for Autheo client.