package eu.dnetlib.openaire.usermanagement.utils;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Map;

@Component
public class HttpUtils {

    private static final Logger logger = Logger.getLogger(HttpUtils.class);

    public JsonElement post(String path, String session, JsonObject body, Map<String, String> params) {
        RestTemplate restTemplate = new RestTemplate();
        String url = path + ((params != null) ? createParams(params) : "");
        HttpHeaders headers = createHeaders(session);
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> request = new HttpEntity<>((body != null)?body.toString():"", headers);
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
        if (responseEntity.getBody() != null) {
            return new JsonParser().parse(responseEntity.getBody());
        } else {
            return null;
        }
    }

    public JsonElement put(String path, String session, JsonObject body) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = createHeaders(session);
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> request = new HttpEntity<>(body.toString(), headers);
        ResponseEntity<String> responseEntity = restTemplate.exchange(path, HttpMethod.PUT, request, String.class);
        if (responseEntity.getBody() != null) {
            return new JsonParser().parse(responseEntity.getBody());
        } else {
            return null;
        }
    }

    public JsonElement get(String path, String session, Map<String, String> params) {
        RestTemplate restTemplate = new RestTemplate();
        String url = path + ((params != null) ? createParams(params) : "");
        HttpHeaders headers = createHeaders(session);
        ResponseEntity<String> responseEntity = restTemplate.exchange
                (url, HttpMethod.GET, new HttpEntity<>(headers), String.class);
        if (responseEntity.getBody() != null) {
            return new JsonParser().parse(responseEntity.getBody());
        } else {
            return null;
        }
    }

    public JsonElement delete(String path, String session, Map<String, String> params) {
        RestTemplate restTemplate = new RestTemplate();
        String url = path + ((params != null) ? createParams(params) : "");
        HttpHeaders headers = createHeaders(session);
        ResponseEntity<String> responseEntity = restTemplate.exchange
                (url, HttpMethod.DELETE, new HttpEntity<>(headers), String.class);
        if (responseEntity.getBody() != null) {
            return new JsonParser().parse(responseEntity.getBody());
        } else {
            return null;
        }
    }


    private String createParams(Map<String, String> params) {
        StringBuilder ret = new StringBuilder("?");
        int count = 0;
        for (Map.Entry<String, String> param : params.entrySet()) {
            ret.append(param.getKey()).append("=");
            ret.append(param.getValue());
            count++;
            if (count != params.entrySet().size()) {
                ret.append("&");
            }
        }
        return ret.toString();
    }

    private HttpHeaders createHeaders(String token) {
        if(token != null) {
            return new HttpHeaders() {{
                set("Session", token);
            }};
        } else {
            return new HttpHeaders();
        }
    }

    public String getCookie(HttpServletRequest req, String cookieName) {
        return Arrays.stream(req.getCookies())
                .filter(c -> c.getName().equals(cookieName))
                .findFirst()
                .map(Cookie::getValue)
                .orElse(null);
    }
}
