package es.sandwatch.trim;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Class containing all report information.
 *
 * @author Ismael Alonso
 * @version 1.0.0
 */
public class Report{
    private List<EndpointReport> endpointReports;


    /**
     * Constructor.
     */
    Report(){
        endpointReports = new ArrayList<>();
    }

    /**
     * Creates an instance of EndpointReport and adds it to the list.
     *
     * @param model the model associated to the report.
     * @param requestResult the result of the request to the above model.
     * @return the report object.
     */
    @NotNull
    EndpointReport addEndpointReport(@NotNull Class<?> model, @NotNull Fetcher.RequestResult requestResult){
        EndpointReport report = new EndpointReport(model, requestResult);
        endpointReports.add(report);
        return report;
    }

    @Override
    public String toString(){
        StringBuilder report = new StringBuilder();
        if (endpointReports.isEmpty()){
            report.append("Nothing to report.");
        }
        else{
            report.append("Trim report, ").append(endpointReports.size()).append(" endpoints:");
            for (EndpointReport endpointReport:endpointReports){
                report.append("\n\n").append(endpointReport);
            }
        }
        return report.toString();
    }


    /**
     * Report for a single model.
     *
     * @author Ismael Alonso
     * @version 1.0.0
     */
    class EndpointReport{
        private Class<?> model;
        private Fetcher.RequestResult requestResult;
        private boolean responseFormatError;
        private Map<String, Boolean> attributeReports;


        /**
         * Constructor.
         *
         * @param model the model associated to the report.
         * @param requestResult the result of the request to the above model.
         */
        private EndpointReport(@NotNull Class<?> model, @NotNull Fetcher.RequestResult requestResult){
            this.model = model;
            this.requestResult = requestResult;
            this.responseFormatError = false;
            this.attributeReports = new HashMap<>();
        }

        /**
         * Lets the report know that the format of the response couldn't be understood.
         */
        void setResponseFormatError(){
            responseFormatError = true;
        }

        /**
         * Adds information about attribute usage to the report.
         *
         * @param attribute the relevant attribute.
         * @param used whether the model uses it.
         */
        void addAttributeReport(@NotNull String attribute, boolean used){
            attributeReports.put(attribute, used);
        }

        @Override
        public String toString(){
            StringBuilder report = new StringBuilder().append(model.toString());
            if (requestResult.requestFailed()){
                report.append("\n  The request could not be performed.");
            }
            else{
                report.append("\n  Request time: ").append(requestResult.getRequestTime()).append("s");
                report.append("\n  Request status code: ").append(requestResult.getStatusCode());
                if (requestResult.is4xx()){
                    report.append("\n  Server response: ").append(requestResult.getResponse());
                }
                else if (responseFormatError){
                    report.append("\n  The format of the response was unknown.");
                }
                else{
                    for (Map.Entry<String, Boolean> entry:attributeReports.entrySet()){
                        report.append("\n    ").append(entry.getKey()).append(": ")
                                .append(entry.getValue() ? "used" : "not used");
                    }
                }
            }
            return report.toString();
        }
    }
}

@@ -3985,10 +3985,1809 @@
 %7D%0A    %7D%0A
+    %0A%0A    /**%0A     * Report for a single attribute.%0A     *%0A     * @author Ismael Alonso%0A     * @version 1.0.0%0A     */%0A    class AttributeReport%7B%0A        private String name;%0A        private boolean used;%0A        private JsonType apiType;%0A        private JsonType modelType;%0A%0A%0A        /**%0A         * Constructor.%0A         *%0A         * @param name the name of the attribute.%0A         */%0A        AttributeReport(String name)%7B%0A            this.name = name;%0A        %7D%0A%0A        /**%0A         * Sets attribute usage information.%0A         *%0A         * @param used true if it is used, false otherwise.%0A         * @return this object.%0A         */%0A        AttributeReport setUsed(boolean used)%7B%0A            this.used = used;%0A            return this;%0A        %7D%0A%0A        /**%0A         * Sets type information.%0A         *%0A         * @param apiType the type found in the API endpoint result.%0A         * @param modelType the type found in the model.%0A         * @return this object%0A         */%0A        AttributeReport setTypes(JsonType apiType, JsonType modelType)%7B%0A            this.apiType = apiType;%0A            this.modelType = modelType;%0A            return this;%0A        %7D%0A%0A        @Override%0A        public String toString() %7B%0A            StringBuilder result = new StringBuilder().append(name).append(%22: %22).append(used ? %22used%22 : %22unused%22);%0A            if (used)%7B%0A                result.append(%22, %22);%0A                if (apiType == modelType)%7B%0A                    result.append(%22types match%22);%0A                %7D%0A                else%7B%0A                    result.append(%22types mismatch (%22)%0A                            .append(apiType).append(%22 in endpoint, %22)%0A                            .append(modelType).append(%22 in model)%22);%0A                %7D%0A            %7D%0A            return result.toString();%0A        %7D%0A    %7D%0A
 %7D%0A

Add AttributeReport