/**
 * This class provides an example of using the DEVS-FIRE API.
 * This example shows how to set up and run a simulation using user-defined GIS fuel/slope/aspect data 
 * and dynamic wind conditions. The procedure of using the API is described below: 
 * 1. connect to the DEVS-FIRE API server and obtain a key, which is needed for all following-on calls. 
 * 2. set wind condition by reading from a wind text file (weather_artificial.txt). 
 * 3. load user-defined fuel, slope, and aspect data from txt files (fuel.txt, slope.txt, aspect.txt). 
 * 4. set ignition point. 
 * 5. run simulation in a stepwise fashion and obtain simulation results (ignited cells and fire perimeter cells). 
 * The simulation results are visulized by the API_FireState_Visualization class.  
 * 
 * Copyright: Systems Integrated Modeling and Simulation (SIMS) Lab, Georgia State University, All Rights Reserved
 * Contact: Prof. Xiaolin Hu (xhu@gsu.edu)
 * Date: April 13 2024
 *
 */

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
import java.sql.Array;
import java.util.ArrayList;


public class MultiStep_userDefinedGIS_dynamicWind {
    public static void main(String[] args) throws IOException, InterruptedException, NoSuchFieldException, IllegalAccessException {
        String base_url = "https://firesim.cs.gsu.edu";

        double lat = 36.7833287;
        double lng = -96.4032697;
        int x = 150;
        int y = 120;

        // Connecting to server
        HttpRequest request1 = HttpRequest.newBuilder()
                .uri(URI.create(base_url+"/api/connectToServer"))
                .header("accept", "application/json")
                .method("POST", HttpRequest.BodyPublishers.ofString("testtest"))
                .build();
        HttpResponse<String> response1 = HttpClient.newHttpClient().send(request1, HttpResponse.BodyHandlers.ofString());
        System.out.println(response1.body());
        String key = response1.body();
        System.out.println(key);

        File weather = new File("weather_artificial.txt");
        Path weatherPath = weather.toPath();
        HttpRequest requestW = HttpRequest.newBuilder()
                .uri(URI.create(base_url+"/api/loadWindFlow/?userToken="+key+"&weatherMap="+weather))
                .header("Content-Type", "text/plain")
                .header("fileName", weatherPath.getFileName().toString())
                .POST(HttpRequest.BodyPublishers.ofFile(weatherPath))
                .build();
        HttpResponse<String> responseW = HttpClient.newHttpClient().send(requestW, HttpResponse.BodyHandlers.ofString());
        //custom maps
        File fuel = new File("fuel.txt");
        Path path = fuel.toPath();
        HttpRequest requestF = HttpRequest.newBuilder()
                .uri(URI.create(base_url+"/api/loadFuel/?userToken="+key+"&fuelMap="+fuel))
                .header("Content-Type", "text/plain")
                .header("fileName", path.getFileName().toString())
                .POST(HttpRequest.BodyPublishers.ofFile(path))
                .build();
        HttpResponse<String> responseF = HttpClient.newHttpClient().send(requestF, HttpResponse.BodyHandlers.ofString());

        
        //----------------------------------------------------
        //Note: if not set explicitly, the default cell resolution is 30m and the default cell space size is 200x200.
        //----------------------------------------------------
        

        File slope = new File("slope.txt");
        Path pathSlope = slope.toPath();
        HttpRequest requestS = HttpRequest.newBuilder()
                .uri(URI.create(base_url+"/api/loadSlope/?userToken="+key+"&slopeMap="+slope))
                .header("Content-Type", "text/plain")
                .header("fileName", pathSlope.getFileName().toString())
                .POST(HttpRequest.BodyPublishers.ofFile(pathSlope))
                .build();
        HttpResponse<String> responseS = HttpClient.newHttpClient().send(requestS, HttpResponse.BodyHandlers.ofString());

        File aspect = new File("aspect.txt");
        Path pathAspect = aspect.toPath();
        HttpRequest requestA = HttpRequest.newBuilder()
                .uri(URI.create(base_url+"/api/loadAspect/?userToken="+key+"&aspectMap="+aspect))
                .header("Content-Type", "text/plain")
                .header("fileName", pathAspect.getFileName().toString())
                .POST(HttpRequest.BodyPublishers.ofFile(pathAspect))
                .build();
        HttpResponse<String> responseA = HttpClient.newHttpClient().send(requestA, HttpResponse.BodyHandlers.ofString());

        //requesting map data
        HttpRequest requestFuel= HttpRequest.newBuilder()
                .uri(URI.create(base_url+"/api/getCellFuel/?userToken="+key))
                .POST(HttpRequest.BodyPublishers.noBody())
                .build();
        HttpResponse<String> responseFuel = HttpClient.newHttpClient().send(requestFuel, HttpResponse.BodyHandlers.ofString());
        System.out.println(responseFuel.body());

//        HttpRequest requestSlope= HttpRequest.newBuilder()
//                .uri(URI.create(base_url+"/api/getCellSlope/?userToken="+key))
//                .POST(HttpRequest.BodyPublishers.noBody())
//                .build();
//        HttpResponse<String> responseSlope = HttpClient.newHttpClient().send(requestSlope, HttpResponse.BodyHandlers.ofString());
//        //System.out.println(responseSlope.body());
//
//        HttpRequest requestAspect= HttpRequest.newBuilder()
//                .uri(URI.create(base_url+"/api/getCellAspect/?userToken="+key))
//                .POST(HttpRequest.BodyPublishers.noBody())
//                .build();
//        HttpResponse<String> responseAspect = HttpClient.newHttpClient().send(requestAspect, HttpResponse.BodyHandlers.ofString());
//        //System.out.println(responseAspect.body());

        //visual Map
        API_FireState_Visualization visual = new API_FireState_Visualization();
        visual.displayFuel(responseFuel.body());
        //visual.displaySlope(responseSlope.body());
        //visual.displayAspect(responseAspect.body());

        //Setting ignition Point
        HttpRequest request4 = HttpRequest.newBuilder()
                .uri(URI.create(base_url+"/api/setPointIgnition/?userToken="+key+"&xs="+x+"&ys="+y))
                .POST(HttpRequest.BodyPublishers.noBody())
                .build();
        HttpResponse<String> response4 = HttpClient.newHttpClient().send(request4, HttpResponse.BodyHandlers.ofString());

        //Run Simulations
        int step = 10;
        double interval = 1000;
        Color perimeterColor = Color.BLUE;
        for(int i = 0; i < step; i++){
            HttpRequest requestSim = HttpRequest.newBuilder()
                    .uri(URI.create(base_url+"/api/continueSimulation/?userToken="+key+"&time="+interval))
                    .POST(HttpRequest.BodyPublishers.noBody())
                    .build();
            HttpResponse<String> responseSim = HttpClient.newHttpClient().send(requestSim, HttpResponse.BodyHandlers.ofString());
            //System.out.println(responseSim.body());

            HttpRequest requestPerimeter= HttpRequest.newBuilder()
                    .uri(URI.create(base_url+"/api/getPerimeterCells/?userToken="+key))
                    .POST(HttpRequest.BodyPublishers.noBody())
                    .build();
            HttpResponse<String> responsePerimeter = HttpClient.newHttpClient().send(requestPerimeter, HttpResponse.BodyHandlers.ofString());
            //System.out.println(responsePerimeter.body());

            visual.visualize(responseSim.body());
            visual.displayPerimeter(responsePerimeter.body(), perimeterColor);
        }
        
        System.out.println("simulation finished!");
    }
}
