import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;

import java.util.ArrayList;

import static io.restassured.RestAssured.given;

public class Server {

    Gson gson = new Gson();
    JsonParser parser = new JsonParser();

    private String clientName;
    private String restUrl;
    private String username;
    private String password;
    private boolean useRelaxedHTTP = false;
    private String persona = "admin";
    private String xAuthToken;
    private JsonArray templateJsonArray;
    private ArrayList<Template> templates = new ArrayList<>();

    public Server(String clientName, String restUrl, String username, String password) {
        this.clientName = clientName;
        this.restUrl = restUrl;
        this.username = username;
        this.password = password;
    }

    public void connect() {
        RestAssured.baseURI = this.restUrl;

        if (useRelaxedHTTP) {
            RestAssured.useRelaxedHTTPSValidation();                                                                       // Ignores SSL issues for testing on lab server, not needed for real cloud servers
        }
        String loginBody = "{" +
                "\"password\":\"" + this.password + "\"," +
                "\"user_id\":\"" + this.username + "\"," +
                "\"persona\":\"" + this.persona + "\"" +
                "}";
        System.out.println("LoginBody: " + loginBody);

        Response loginResponse = given().
                contentType(ContentType.JSON).
                body(loginBody).
                when().
                put("/session/login");


        String loginResponseString = loginResponse.asString();
        System.out.println(loginResponseString);
        JsonPath loginResponseJson = new JsonPath(loginResponseString);
        this.xAuthToken = (loginResponseJson.get("X-Auth-Token"));
    }

    public void getJsonTemplateArrayFromRestApi() {
        RestAssured.baseURI = this.restUrl;

        Response getTemplatesResponse = null;
        boolean noResponse = true;

        while (noResponse) {

            try {
                getTemplatesResponse = given().
                        contentType(ContentType.JSON).
                        header("X-Auth-Token", this.xAuthToken).
                        when().
                        get("/templates/search");

                int statusCode = getTemplatesResponse.getStatusCode();

                if (statusCode == 200) {
                    noResponse = false;
                } else {
                    System.out.println("Status Code: " + statusCode);
                    System.out.println(getTemplatesResponse.asString());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        String getTemplateResponseString = getTemplatesResponse.asString();
        JsonObject getTemplateResponseDataObject = this.parser.parse(getTemplateResponseString).getAsJsonObject();
        this.templateJsonArray = getTemplateResponseDataObject.get("data").getAsJsonArray();
    }

    public void printTemplateList() {

        for (int x = 0; x < this.templateJsonArray.size(); x++) {
            String nameTitle = "Name: ";
            String idTitle = "ID: ";
            String wsName = this.templateJsonArray.get(x).getAsJsonObject().get("name").getAsString();
            String wsID = this.templateJsonArray.get(x).getAsJsonObject().get("workspace_id").getAsString();
            System.out.format("%-5s |%-10s %-40s|%-10s %-20s|%n", x + ")", nameTitle, wsName, idTitle, wsID);
        }
    }

    public void saveTemplatesFromJsonArray() {

        for (int x = 0; x < this.templateJsonArray.size(); x++) {
            this.templates.add(new Template(this.templateJsonArray.get(x).getAsJsonObject()));
        }
    }

    public void getAndSaveAllFoldersFromJsonArray(){

//        for(int x = 0; x < templates.size(); x++){
        for(int x = 1; x < 2; x++){                     //run once as test

            Template currentTemplate = this.templates.get(x);
          //  Folder currentSubfolder;

            if (currentTemplate.hasSubfolders()){
                getSubfoldersJsonArrayFromRestApi(currentTemplate);

                for (int y = 0; y < currentTemplate.getFoldersJsonArray().size(); y++) {                                                                                     // for each template (x) in 'templates' get  foldersJsonArray.size and for each folder

                    JsonObject fullSubfolderProfileObject = getFolderProfileFromRestApi(currentTemplate.getFoldersJsonArray().get(y).getAsJsonObject());
                   // System.out.println(fullSubfolderProfileObject);
                   Folder currentSubfolder = currentTemplate.addSubfolder(fullSubfolderProfileObject);
                   if (currentSubfolder.hasSubfolders()) {
                       saveSubfoldersRecursively(currentSubfolder);
                   }
                    if (currentSubfolder.getId().equals("Active!422") ) {
                        System.out.println("inside if");
                        System.out.println("access test 1: " + currentSubfolder.getId() + " subfolder at index 0: " + currentSubfolder.getSubFolders().get(0));
                        System.out.println("access test 2: " + getSingleTemplate(1).getSubFolders().get(0).getSubFolders().get(0) + " subfolder at index 0: " + currentSubfolder.getSubFolders().get(0));
                    }
                }
            }
        }
        System.out.println("in getAndSaveAllFoldersFromJsonArray test at end");
        System.out.println("access test 1: " + getSingleTemplate(1).getSubFolders().get(0).getId() + " subfolder at index 0: " + getSingleTemplate(1).getSubFolders().get(0).getSubFolders().get(0).toString());
    }

    public void saveSubfoldersRecursively(Folder folder){

        if (folder.hasSubfolders()){
            getSubfoldersJsonArrayFromRestApi(folder);

            for(int x = 0; x < folder.getFoldersJsonArray().size(); x++) {
                JsonObject currentSubfolderJsonArrayObject = folder.getFoldersJsonArray().get(x).getAsJsonObject();
                JsonObject fullSubfolderProfileObject = getFolderProfileFromRestApi(currentSubfolderJsonArrayObject);
                Folder newSubfolder = folder.addSubfolder(fullSubfolderProfileObject);
                if (newSubfolder.hasSubfolders()) {
                    saveSubfoldersRecursively(newSubfolder);
                }
            }
            if (folder.getId().equals("Active!422") ) {
                System.out.println("inside saveSubfoldersRecursively");
                System.out.println("access test 1: " + folder.getId() + " subfolder at index 0: " + folder.getSubFolders().get(0));
                //System.out.println("access test 2: " + getSingleTemplate(1).getSubFolders().get(0).getId() + " subfolder at index 0: " + getSingleTemplate(1).getSubFolders().get(0).getSubFolders().get(0).toString());
            }
        }
    }

    public JsonObject getFolderProfileFromRestApi(JsonObject folderProfileObject){

            RestAssured.baseURI = this.restUrl;

            Response getFolderProfileResponse = null;
            boolean noResponse = true;

        System.out.println("getFolderProfileFromRestApi - " + folderProfileObject.get("id").getAsString());

            while (noResponse) {

                try {
                    getFolderProfileResponse = given().
                            contentType(ContentType.JSON).
                            header("X-Auth-Token", this.xAuthToken).
                            when().
                            get("/folders/" + folderProfileObject.get("id").getAsString());

                    int statusCode = getFolderProfileResponse.getStatusCode();

                    if (statusCode == 200) {
                        noResponse = false;
                    } else {
                        System.out.println("Status Code: " + statusCode);
                        System.out.println(getFolderProfileResponse.asString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            String getFolderProfileResponseString = getFolderProfileResponse.asString();
            JsonObject getFolderProfileResponseDataObject = parser.parse(getFolderProfileResponseString).getAsJsonObject();

            return getFolderProfileResponseDataObject.get("data").getAsJsonObject();
        }

    public void printTemplateProfile(int x) {
        System.out.println(this.templates.get(x).toString());
    }

    public void getSubfoldersJsonArrayFromRestApi(IMContainer container) {
        if (container.hasSubfolders() == true) {
            RestAssured.baseURI = this.restUrl;

            Response getFoldersResponse = null;
            boolean noResponse = true;

            while (noResponse) {

                try {
                    getFoldersResponse = given().
                            contentType(ContentType.JSON).
                            header("X-Auth-Token", this.xAuthToken).
                            when().
                            get("/" + container.getWsType() + "s/" + container.getId() + "/children");              //wsType is "folder" for folders and tabs and "workspace" for templates which corresponds to the endpoint needed.

                    int statusCode = getFoldersResponse.getStatusCode();

                    if (statusCode == 200) {
                        noResponse = false;
                    } else {
                        System.out.println("Status Code: " + statusCode);
                        System.out.println(getFoldersResponse.asString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            String getFoldersResponseString = getFoldersResponse.asString();
            JsonObject getTemplateResponseDataObject = parser.parse(getFoldersResponseString).getAsJsonObject();
            container.setFoldersJsonArray(getTemplateResponseDataObject.get("data").getAsJsonArray());
        }
    }

    public void printStructure(IMContainer container, String indent){

        System.out.println(indent + container.getName());

        if (container.hasSubfolders()){

            for (Folder subFolder: container.getSubFolders())
            printStructure(subFolder, indent + "        ");
        }



    }

    public void printFolderList(IMContainer template) {

        if (template.hasSubfolders()) {
            for (int x = 0; x < template.getSubFolders().size(); x++) {
                String nameTitle = "Name: ";
                String idTitle = "ID: ";
                String folderName = template.getSubFolders().get(x).getName();
                String folderID = template.getSubFolders().get(x).getId();
                System.out.format("%-5s |%-10s %-40s|%-10s %-20s|%n", x + ")", nameTitle, folderName, idTitle, folderID);
            }
        }
    }


    //<editor-fold desc="Getters"


    public Template getSingleTemplate(int x){
        return templates.get(x);
    }

    public String getClientName() {
        return clientName;
    }

    public String getRestUrl() {
        return restUrl;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public boolean isUseRelaxedHTTP() {
        return useRelaxedHTTP;
    }

    public String getPersona() {
        return persona;
    }

    public String getxAuthToken() {
        return xAuthToken;
    }

    //</editor-fold>

    //<editor-fold desc="Setters"

    public void setClientName(String clientName) {
        this.clientName = clientName;
    }

    public void setRestUrl(String restUrl) {
        this.restUrl = restUrl;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setUseRelaxedHTTP(boolean useRelaxedHTTP) {
        this.useRelaxedHTTP = useRelaxedHTTP;
    }

    public void setPersona(String persona) {
        this.persona = persona;
    }

    public void setxAuthToken(String xAuthToken) {
        this.xAuthToken = xAuthToken;
    }

    //</editor-fold>
}
