/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.cryptolib.interoperation.js.commands;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Custom exception class for the interoperation tests that allows the storing
 * of additional data that can be used for debugging purposes.
 */
public class CommandException extends Exception {

    private static final long serialVersionUID = 1426689542538859934L;

    private final String message;

    private final Throwable cause;

    private final Map<String, String> dataMap;

    private CommandException(final String message, final Throwable cause,
            Map<String, String> dataMap) {
        super(message, cause);

        this.cause = cause;
        this.message = message;
        this.dataMap = dataMap;
    }

    @Override
    public String getMessage() {

        StringBuilder builder = new StringBuilder();

        builder.append("\n\n");

        if (!message.isEmpty()) {
            builder.append("Message: " + message + "\n\n");
        }

        if (!cause.getMessage().isEmpty()) {
            builder.append("Cause: " + cause.getMessage() + "\n\n");
        }

        String className = this.getClass().getSimpleName();
        if (dataMap.size() > 0) {
            builder.append("[Begin " + className + " data]\n\n");
            for (Map.Entry<String, String> entry : dataMap.entrySet()) {
                builder.append(
                    entry.getKey() + ": " + entry.getValue() + "\n\n");
            }
            builder.append("[End " + className + " data]\n\n");
        }

        return builder.toString();
    }

    public static class Builder {

        private String message;

        private Throwable cause;

        private Map<String, String> dataMap;

        /**
         * Constructor for a {@link CommandException} instance to build.
         * 
         * @param cause
         *            the cause of the {@link CommandException} instance to
         *            build.
         */
        public Builder() {

            message = "";
            cause = new Throwable("");
            dataMap = new LinkedHashMap<>();
        }

        /**
         * Adds a message for the {@link CommandException} instance to build.
         * 
         * @param message
         *            the message to add.
         * @return the updated {@link CommandException.Builder} instance.
         */
        public Builder addMessage(String message) {

            this.message = message;

            return this;
        }

        /**
         * Adds a cause for the {@link CommandException} instance to build.
         * 
         * @param cause
         *            the cause to add.
         * @return the updated {@link CommandException.Builder} instance.
         */
        public Builder addCause(Throwable cause) {

            this.cause = cause;

            return this;
        }

        /**
         * Adds some data for the {@link CommandException} instance to build.
         * 
         * @param description
         *            the description of the data.
         * @param valueStr
         *            the value of the data, in String format.
         * @return the updated {@link CommandException.Builder} instance.
         */
        public Builder addData(String description, String valueStr) {

            dataMap.put(description, valueStr);

            return this;
        }

        /**
         * Builds the {@link CommandException} instance.
         * 
         * @return the {@link CommandException} instance.
         */

        public CommandException build() {

            return new CommandException(message, cause, dataMap);
        }
    }
}
