import java.io.*;
import java.net.HttpURLConnection;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

import static java.lang.System.exit;


public class UpdateDocumentTutorial {

    // Replace with your HostMyApi Data Table URL
    private static String HOST_MY_API_TABLE_URL;
    // Replace with your HostMyApi Access Key
    private static String HOST_MY_API_KEY_ID;
    // Replace with your HostMyApi Document Record Identifier
    private static String HOST_MY_API_RECORD_ID;


    public static void main(String[] args) {
        System.out.println("Current directory: " + System.getProperty("user.dir"));

        System.out.println("Arguments Passed: " + args.length);
        for (int i = 0; i < args.length; i++) {
            System.out.println("Argument " + i + " is: " + args[i]);
        }
        if (args.length < 3) {
            System.out.println();
            System.out.println("Error: " + "Must provide 3 arguments for <TABLE URL>, <KEY ID> and <RECORD ID>.");
            exit(-1);
        } else {

            HOST_MY_API_TABLE_URL = args[0];
            HOST_MY_API_KEY_ID = args[1];
            HOST_MY_API_RECORD_ID = args[2];
            System.out.println();
            System.out.println("Information: " + "TABLE URL used is " + HOST_MY_API_TABLE_URL);
            System.out.println("Information: " + "KEY ID used is " + HOST_MY_API_KEY_ID);
            System.out.println("Information: " + "RECORD ID used is " + HOST_MY_API_RECORD_ID);
            System.out.println();

            try {
                String urlGetString = "https://api.hostmy.io/v2/records/" + HOST_MY_API_RECORD_ID + "?key=" + HOST_MY_API_TABLE_URL;
                System.out.println("URL GET: " + urlGetString);
                var urlGet = URI.create(urlGetString).toURL();
                HttpURLConnection connectionGet = (HttpURLConnection) urlGet.openConnection();
                // Set Header with the HostMyApi Access Key
                connectionGet.setRequestProperty("X-API-KEY", HOST_MY_API_KEY_ID);
                // Get Original Document
                connectionGet.setRequestMethod("GET");
                int responseCodeGet = connectionGet.getResponseCode();
                if (responseCodeGet == HttpURLConnection.HTTP_OK) { // success
                    // Original Document Record GET has succeeded, now display and modify
                    System.out.println();
                    System.out.println("Original Document GET:");
                    BufferedReader inGet = new BufferedReader(new InputStreamReader(connectionGet.getInputStream(), StandardCharsets.UTF_8));
                    String inputLineGet;
                    while ((inputLineGet = inGet.readLine()) != null) {
                        System.out.println(inputLineGet);
                    }
                    inGet.close();
                    connectionGet.disconnect();
                    //
                    // Modify the Original Documents Record
                    //
                    // Set PATCH request
                    String urlPatchString = "https://api.hostmy.io/v2/records/" + HOST_MY_API_RECORD_ID + "?key=" + HOST_MY_API_TABLE_URL;
                    System.out.println("URL GET: " + urlPatchString);
                    var urlPatch = URI.create(urlGetString).toURL();
                    HttpURLConnection connectionPatch = (HttpURLConnection) urlPatch.openConnection();
                    // Set Header with the HostMyApi Access Key
                    connectionPatch.setRequestProperty("X-API-KEY", HOST_MY_API_KEY_ID);
                    // Use of POST and X-HTTP-Method-Override has been implemented as a workaround to using PATCH with the standard JAVA HttpURLConnection library
                    // Other libraries will work with only a setRequestMethod("PATCH") and no X-HTTP-Method-Override PATCH header parameter
                    // E.g. Apache httpclient 4.5.13 will work with connectionPatch.setRequestMethod("PATCH")
                    //            <groupId>org.apache.httpcomponents</groupId>
                    //            <artifactId>httpclient</artifactId>
                    //            <version>4.5.13</version>
                    connectionPatch.setRequestMethod("POST");
                    connectionPatch.setRequestProperty("X-HTTP-Method-Override", "PATCH");
                    connectionPatch.setRequestProperty("accept", "*/*");
                    connectionPatch.setRequestProperty("Content-Type", "application/json-patch+json");
                    connectionPatch.setDoOutput(true);
                    connectionPatch.setDoInput(true);
                    OutputStream os = connectionPatch.getOutputStream();
                    OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
                    // Create JSON Patch Operation in request body: [{"op":"replace","path":"/dayShort_de","value":"Sa"}]
                    // See https://en.wikipedia.org/wiki/JSON_Patch for more information on JSON Patch Operations
                    osw.write("[{\"op\":\"replace\",\"path\":\"/dayShort_de\",\"value\":\"Sa\"}]");
                    osw.flush();
                    osw.close();
                    os.close();  //don't forget to close the OutputStream

                    int responseCodePatch = connectionPatch.getResponseCode();
                    if (responseCodePatch == HttpURLConnection.HTTP_OK) { // success
                        // Patch has succeeded to change the Original Document, now display and modify
                        System.out.println();
                        System.out.println("Updated Document PATCH:");
                        BufferedReader inPatch = new BufferedReader(new InputStreamReader(connectionPatch.getInputStream(), StandardCharsets.UTF_8));
                        String inputLinePatch;
                        while ((inputLinePatch = inPatch.readLine()) != null) {
                            System.out.println(inputLinePatch);
                        }
                        inPatch.close();
                        connectionPatch.disconnect();
                    } else {
                        System.out.println("HostMyApi Data request has not worked");
                        System.out.println("status: " + responseCodePatch);
                        System.out.println("error: \"" + "\"");
                        System.out.println("message: \"" + "\"");
                        System.out.println("path: \"" + urlPatch.getPath() + "\"");
                        System.out.println();
                        //
                        // Try to emulate Curl error response:
                        // timestamp: 1723546524584
                        // status: 400
                        // error: "Bad Request"
                        // message: "You must provide an api key for this request" from HTTP Status Message
                        // path: "/v2/tables/T-c4b024cf-ad56-4b93-a4c7-ccfa501c3929"
                        //
                        System.out.println("PATCH request has not worked");
                        BufferedReader errorReader = new BufferedReader(new InputStreamReader(connectionPatch.getErrorStream(), StandardCharsets.UTF_8));
                        String errorLine;
                        StringBuilder errorContent = new StringBuilder();
                        while ((errorLine = errorReader.readLine()) != null) {
                            errorContent.append(errorLine);
                            System.out.println(errorLine);
                        }
                        errorReader.close();
                        System.out.println("Error Response: " + errorContent.toString());


                        Map<String, List<String>> map = connectionPatch.getHeaderFields();
                        System.out.println("Printing All Response Header for URL: " + HOST_MY_API_TABLE_URL + "\n");
                        for (Map.Entry<String, List<String>> entry : map.entrySet()) {
                            System.out.println(entry.getKey() + " : " + entry.getValue());
                        }

                    }

                } else {
                    // Original Document Read has failed
                    System.out.println("HostMyApi Data request has not worked");
                    System.out.println("status: " + responseCodeGet);
                    System.out.println("error: \"" + "\"");
                    System.out.println("message: \"" + "\"");
                    System.out.println("path: \"" + urlGet.getPath() + "\"");
                    System.out.println();
                    /**
                     * Emulate Curl error response:
                     * timestamp: 1723546524584
                     * status: 400
                     * error: "Bad Request"
                     * message: "You must provide an api key for this request" from HTTP Status Message
                     * path: "/v2/tables/T-c4b024cf-ad56-4b93-a4c7-ccfa501c3929"
                     */
                    System.out.println("Original Document GET request has not worked");
                    BufferedReader errorReader = new BufferedReader(new InputStreamReader(connectionGet.getErrorStream(), StandardCharsets.UTF_8));
                    String errorLine;
                    StringBuilder errorContent = new StringBuilder();
                    while ((errorLine = errorReader.readLine()) != null) {
                        errorContent.append(errorLine);
                        System.out.println(errorLine);
                    }
                    errorReader.close();
                    System.out.println("Error Response: " + errorContent.toString());


                    Map<String, List<String>> map = connectionGet.getHeaderFields();
                    System.out.println("Printing All Response Header for URL: " + HOST_MY_API_TABLE_URL + "\n");
                    for (Map.Entry<String, List<String>> entry : map.entrySet()) {
                        System.out.println(entry.getKey() + " : " + entry.getValue());
                    }


                }

            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}