package code;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.KeyManagerFactory;
import java.security.KeyStore;
import javax.net.ssl.TrustManagerFactory;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.bouncycastle.openssl.PEMParser;
import java.io.FileReader;
import java.io.FileInputStream;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import java.security.cert.CertificateFactory;
import java.io.BufferedInputStream;
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import java.security.KeyPair;

import org.json.JSONException;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpsExchange;
import com.sun.net.httpserver.HttpExchange;
import java.net.HttpURLConnection;

public class Helper {

	private static String keycloakRealm = "test00";
	private static String keycloakURL = "http://localhost:8080/";
	private static String cloudappURL = "http://localhost:3002/";
	private static String selfURL = "https://localhost:3001";


	public static void sendCors(HttpExchange exchange, int stato, String response) throws IOException {
		Headers headers = exchange.getResponseHeaders();
		headers.add("Access-Control-Allow-Origin", "*");// se non mettiamo *, viene errore CORS //http://localhost:3001/secured/domains
		headers.add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
		headers.add("Access-Control-Allow-Headers", "Content-Type,Authorization");
		if(response == null){
			exchange.sendResponseHeaders(stato, -1);
			return;
		}
		byte[] responseBytes = response.getBytes();
		exchange.sendResponseHeaders(200, responseBytes.length);
		OutputStream os = exchange.getResponseBody();
		os.write(responseBytes);
		os.close();
	}

	public static void sendCors(HttpExchange exchange, int stato) throws IOException {
		sendCors(exchange, stato, null);
	}

	public static void sendCors(HttpExchange exchange, String response) throws IOException {
		sendCors(exchange, 200, response);
	}

	public static String checkTokenGetUser(HttpExchange exchange) {
		String token = exchange.getRequestHeaders().get("Authorization").get(0).substring(7);// taglio bearer
		String[] tokSplit = token.split("[.]");
		if(tokSplit.length != 3) return null;
		String signature = tokSplit[2];
		try {
			return TokenHandler.verificaToken(token, signature);
		} catch (NoSuchAlgorithmException | IOException | JSONException e) {
			e.printStackTrace();
			return null;
		}
	}

	public static Map<String, Object> parseQuery(String query) throws UnsupportedEncodingException {
		if(query == null) throw new IllegalArgumentException("Query string can't be null");

		Map<String, Object> result = new HashMap<String, Object>();
		String pairs[] = query.split("[&]");
		for (String pair : pairs) {
			String param[] = pair.split("[=]");
			String key = null;
			String value = null;
			if (param.length > 0) {
				key = URLDecoder.decode(param[0], System.getProperty("file.encoding"));
			}

			if (param.length > 1) {
				value = URLDecoder.decode(param[1], System.getProperty("file.encoding"));
			}

			if (result.containsKey(key)) {
				Object obj = result.get(key);
				if (obj instanceof List<?>) {
					@SuppressWarnings("unchecked")
					List<String> values = (List<String>) obj;
					values.add(value);
				} else if (obj instanceof String) {
					List<String> values = new ArrayList<String>();
					values.add((String) obj);
					values.add(value);
					result.put(key, values);
				}
			} else {
				result.put(key, value);
			}
		}
		return result;
	}

	public static String readBody(InputStream requestBody) {
		int request;
		StringBuffer response = new StringBuffer();
		try {
			while ((request = requestBody.read()) != -1)
				response.append(Character.toString((char) request));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return response.toString();
	}

	public static HttpURLConnection sendMessageToCloudapp(String path, String message) throws IOException {
		URL url = new URL(getCloudappURL() + (path.startsWith("/") ? path.substring(1) : path));
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		setConnectionSettings(connection,"POST");
		DataOutputStream outStream = new DataOutputStream(connection.getOutputStream());//inserimento param in call
		outStream.writeBytes(message);
		outStream.flush();
		outStream.close();
		return connection;
	}

	public static void setConnectionSettings(HttpURLConnection connection, String method) throws IOException{
		connection.setRequestMethod(method);
		connection.setRequestProperty("Content-Type", "application/json");
		connection.setRequestProperty("Accept", "application/json");
		connection.setDoOutput(true);
		connection.setConnectTimeout(5000);
		connection.setReadTimeout(5000);
	}

	public static String getResponseFromConnection(HttpsURLConnection con) throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
		String inputLine;
		StringBuffer content = new StringBuffer();
		while ((inputLine = reader.readLine()) != null) {
			content.append(inputLine);
		}
		reader.close();
		return content.toString();
	}

	public static String getKeycloakRealm(){
		return keycloakRealm;
	}

	public static String getKeycloakURL(){
		return keycloakURL;
	}

	public static String getCloudappURL(){
		return cloudappURL;
	}

	public static String getSelfURL(){
		return selfURL;
	}

}