package com.bb.service;

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

import io.netty.channel.ConnectTimeoutException;
import io.netty.handler.timeout.ReadTimeoutException;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
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 SvendorServiceImpl implements SvendorService {
	
	@Autowired
	WebClient webClient;
	
	
	@Override
	public JSONObject getDetail(HashMap betInfo) throws JSONException {
		JSONObject resJson = new JSONObject();
		//body
		MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
		parameters.add("trid", betInfo.get("vendorTranKey").toString());
		
		HttpHeaders header = new HttpHeaders(); 	
		header.set("Authorization", betInfo.get("vendorApiKey").toString());
		header.set("Content-Type", "application/x-www-form-urlencoded");
		
		try {
			ResponseEntity<String> responseEntity = webClient.post()
					.uri(betInfo.get("vendorApiUrl").toString()+"/transaction-single")
					.headers(h -> h.addAll(header))
					.bodyValue(parameters)
					.retrieve()
					.toEntity(String.class)
					.block();
			
			log.info(responseEntity.getBody());
			resJson = new JSONObject(responseEntity.getBody());
			
		} catch(WebClientResponseException e) {
			log.error("getDetail WebClientResponseException: " + e.getMessage());
			log.error("getDetail status code: " + e.getStatusCode().value());
			log.error("getDetail response body: " + e.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error("getDetail ConnectTimeoutException::"+rae.getMessage());
            }
            if(rae.getCause() instanceof ReadTimeoutException) {
            	log.error("getDetail ReadTimeoutException::"+rae.getMessage());
            }
            if(rae.getCause() instanceof InterruptedException) {
            	log.error("getDetail InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error("getDetail Exception::"+e.getMessage());
		}
		return resJson.getJSONObject("data").getJSONObject("gameDetail");
	}


	@Override
	public JSONObject create(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		JSONObject resJson = new JSONObject();
		
		//body
		MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
		parameters.add("userid", apiInfo.get("userid").toString());
		parameters.add("nickname", apiInfo.get("nickname").toString());
		
		HttpHeaders header = new HttpHeaders(); 	
		header.set("Content-Type", "application/x-www-form-urlencoded");
		header.set("Authorization", apiInfo.get("apiKey").toString());
		log.info(LOG_PREFIX+ "create::Request::"+parameters.toString());
		
		try {
			ResponseEntity<String> responseEntity = webClient.post()
					.uri(apiInfo.get("apiBaseUrl").toString()+"/create")
					.headers(h -> h.addAll(header))
					.bodyValue(parameters)
					.retrieve()
					.toEntity(String.class)
					.block();
			log.info(LOG_PREFIX+ "create::Response::"+responseEntity.getBody());
			resJson = new JSONObject(responseEntity.getBody());
		} catch(WebClientResponseException e) {
			log.error(LOG_PREFIX+ "create WebClientResponseException: " + e.getMessage());
			log.error(LOG_PREFIX+ "create status code: " + e.getStatusCode().value());
			log.error(LOG_PREFIX+ "create response body: " + e.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "create ConnectTimeoutException::"+rae.getMessage());
            }
            if(rae.getCause() instanceof ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "create ReadTimeoutException::"+rae.getMessage());
            }
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "create InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.info(LOG_PREFIX+ "create::Exception::"+e.getMessage());
		}
		
		return resJson;
	}


	@Override
	public List<Game> gameList(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		List<Game> gameList = null;
		
		//body
		MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
		parameters.add("vendor", apiInfo.get("vendor").toString());
		
		HttpHeaders header = new HttpHeaders(); 	
		header.set("Content-Type", "application/x-www-form-urlencoded");
		header.set("Authorization", apiInfo.get("apiKey").toString());
		log.info(LOG_PREFIX+ "gameList::Request::"+parameters.toString());
		
		try {
			ResponseEntity<String> responseEntity = webClient.post()
					.uri(apiInfo.get("apiBaseUrl").toString()+"/gamelist")
					.headers(h -> h.addAll(header))
					.bodyValue(parameters)
					.retrieve()
					.toEntity(String.class)
					.block();
			JSONObject resJson = new JSONObject(responseEntity.getBody());
			if(resJson.getInt("code") == 0) {
				log.info(LOG_PREFIX+ "gameList::Response::code::"+resJson.getInt("code"));
				log.info(LOG_PREFIX+ "gameList::Response::msg::"+resJson.getString("msg"));
				JSONArray games = resJson.getJSONArray("data");
				int length = games.length();
				gameList = new ArrayList<>();
				
				for(int i=0; i<length; i++) {
					Game game = new Game();
					JSONObject objGame = games.getJSONObject(i);
					game.setGameIdx(i+1);
					game.setGameKey(objGame.getString("game"));
					game.setGameName(objGame.getString("kname"));
					game.setGameNameEn(objGame.getString("name"));
					game.setGameImg(objGame.getString("imageurl"));
					gameList.add(game);
				}
			}
		} catch(WebClientResponseException e) {
			log.error(LOG_PREFIX+ "gameList WebClientResponseException: " + e.getMessage());
			log.error(LOG_PREFIX+ "gameList status code: " + e.getStatusCode().value());
			log.error(LOG_PREFIX+ "gameList response body: " + e.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "gameList ConnectTimeoutException::"+rae.getMessage());
            }
            if(rae.getCause() instanceof ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "gameList ReadTimeoutException::"+rae.getMessage());
            }
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "gameList InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.info(LOG_PREFIX+ "gameList::Exception::"+e.getMessage());
		}
		
		return gameList;
	}


	@Override
	public String playUrl(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		String url = null;
		
		//body
		MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
		parameters.add("userid", apiInfo.get("userid").toString());
		parameters.add("userip", apiInfo.get("userip").toString());
		parameters.add("vendor", apiInfo.get("vendor").toString());	
		parameters.add("game", apiInfo.get("game").toString());
		if("Evolution".equals(apiInfo.get("vendor").toString())) {
			parameters.add("skin", apiInfo.get("skin").toString());
		}
		
		HttpHeaders header = new HttpHeaders(); 	
		header.set("Content-Type", "application/x-www-form-urlencoded");
		header.set("Authorization", apiInfo.get("apiKey").toString());
		log.info(LOG_PREFIX+ "playUrl::Request::"+parameters.toString());
		
		try {
			ResponseEntity<String> responseEntity = webClient.post()
					.uri(apiInfo.get("apiBaseUrl").toString()+"/play")
					.headers(h -> h.addAll(header))
					.bodyValue(parameters)
					.retrieve()
					.toEntity(String.class)
					.block();
			log.info(LOG_PREFIX+ "playUrl::Response::"+responseEntity.getBody());
			JSONObject resJson = new JSONObject(responseEntity.getBody());
			if(resJson.getInt("code") == 0) {
				url = resJson.getString("URL");
			}
		} catch(WebClientResponseException e) {
			log.error(LOG_PREFIX+ "playUrl WebClientResponseException: " + e.getMessage());
			log.error(LOG_PREFIX+ "playUrl status code: " + e.getStatusCode().value());
			log.error(LOG_PREFIX+ "playUrl response body: " + e.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "playUrl ConnectTimeoutException::"+rae.getMessage());
            }
            if(rae.getCause() instanceof ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "playUrl ReadTimeoutException::"+rae.getMessage());
            }
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "playUrl InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.info(LOG_PREFIX+ "playUrl::Exception::"+e.getMessage());
		}
		
		return url;
	}


	@Override
	public JSONObject getDetail(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		JSONObject dataObj = null;
		
		//body
		MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
		parameters.add("trid", apiInfo.get("uuid").toString());
		
		HttpHeaders header = new HttpHeaders(); 	
		header.set("Content-Type", "application/x-www-form-urlencoded");
		header.set("Authorization", apiInfo.get("vendorApiKey").toString());
		log.info(LOG_PREFIX+ "getDetail::Request::"+parameters.toString());
		
		try {
			ResponseEntity<String> responseEntity = webClient.post()
					.uri(apiInfo.get("vendorApiUrl").toString()+"/transaction-single")
					.headers(h -> h.addAll(header))
					.bodyValue(parameters)
					.retrieve()
					.toEntity(String.class)
					.block();
			JSONObject resJson = new JSONObject(responseEntity.getBody());
			log.info(LOG_PREFIX+ "getDetail::Response::"+resJson);
			int resCode = resJson.getInt("code");
			String resMsg = resJson.getString("msg");
			log.info(LOG_PREFIX+ "getDetail::Response::Code::"+resCode);
			log.info(LOG_PREFIX+ "getDetail::Response::Message::"+resMsg);
			if(resCode == 0) {
				dataObj = resJson.getJSONObject("data");
			}
		} catch(WebClientResponseException e) {
			log.error(LOG_PREFIX+ "getDetail WebClientResponseException: " + e.getMessage());
			log.error(LOG_PREFIX+ "getDetail status code: " + e.getStatusCode().value());
			log.error(LOG_PREFIX+ "getDetail response body: " + e.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "getDetail ConnectTimeoutException::"+rae.getMessage());
            }
            if(rae.getCause() instanceof ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "getDetail ReadTimeoutException::"+rae.getMessage());
            }
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "getDetail InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.info(LOG_PREFIX+ "getDetail::Exception::"+e.getMessage());
		}
		
		return dataObj;
	}
}
