package com.bb.service;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientRequestException;
import org.springframework.web.reactive.function.client.WebClientResponseException;

import com.bb.model.Game;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class PandaServiceImpl implements PandaService {
	
	@Autowired
	WebClient webClient;
	
	
	@Override
	public List<Game> getGameList(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "getGameList::";
		List<Game> gameList = null;
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/game/gamelist?";
		String param = "&vendor="+apiInfo.get("apiVendor");
		apiUrl = apiUrl + param;
		log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
		
		try {
			ResponseEntity<String> resEntity = webClient.get()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				JSONArray games = new JSONArray(resEntity.getBody());
				int length = games.length();
				gameList = new ArrayList<>();
				
				for(int i=0; i<length; i++) {
					Game game = new Game();
					JSONObject objGame = games.getJSONObject(i);
					String type = objGame.getString("type");
					
					if(objGame.has("details") && !objGame.isNull("details")) {
						game.setGameIdx(i+1);
						game.setGameKey(objGame.getString("id"));
						game.setGameName(objGame.getString("title_ko"));
						game.setGameNameEn(objGame.getString("title"));
						game.setGameImg(objGame.getJSONObject("details").getString("thumbnail"));
						game.setGameType(type);
						gameList.add(game);
					}
				}
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return gameList;
	}

	@Override
	public String getLaunchUrl(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "getLaunchUrl::";
		String luanchUrl = "";
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/game/launch?";
		String param = "vendor="+apiInfo.get("apiVendor")+"&username="+apiInfo.get("apiUsername")
				+"&game_id="+apiInfo.get("apiGameCode")+"&nick_name="+apiInfo.get("apiNickname");
		apiUrl = apiUrl + param;
		log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
		
		try {
			ResponseEntity<String> resEntity = webClient.get()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				JSONObject responseObj = new JSONObject(resEntity.getBody());
				log.info(LOG_PREFIX+ "Response : " + responseObj.toString());
				
				luanchUrl = responseObj.getString("url");
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return luanchUrl;
	}

	@Override
	public String getDetail(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "getDetail::";
		String detailUrl = "";
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/transaction/transaction/"+apiInfo.get("tranId");
		log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
		
		try {
			ResponseEntity<String> resEntity = webClient.get()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				JSONObject responseObj = new JSONObject(resEntity.getBody());
				log.info(LOG_PREFIX+ "Response : " + responseObj.toString());
				
				JSONArray data = responseObj.optJSONArray("data");
				if(data != null) {
					detailUrl = data.optJSONObject(0).optJSONObject("dynamo_raw").optJSONObject("external").optJSONObject("detail").getString("url");
				}
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return detailUrl;
	}

}
