package demo.mapi.ccv.eu.mapi_demo.formatters;

import eu.ccvlab.mapi.core.MAPIError;
import eu.ccvlab.mapi.core.Result;
import eu.ccvlab.mapi.core.payment.TextLine;
import eu.ccvlab.mapi.core.requests.ResultState;
import org.apache.commons.lang.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Helper class to printFormatted output of a ticket to resemble a real paper ticket (ascii-wise)
 */
public class OutputFormatter {

    private final OutputAppender appender;

    public interface OutputAppender {
        /**
         * Appens the provided characters to the output. Newline needs to be added explicitly.
         * @param line
         */
        public void append(String line);
    }

    public OutputFormatter(OutputAppender output) {
        appender = output;
    }

    public void printTicket(List<String> lines) {
        int maxWidth = getMaxWidth(lines)+2;
        printCutoffLine(appender, maxWidth);

        for (String line: lines) {
            appender.append(String.format("| %s%s |\n", line, "                                                                                  ".substring(0,maxWidth-line.length())));
        }
        printCutoffLine(appender, maxWidth);
    }

    public void printTicketLines(List<TextLine> lines) {
        int maxWidth = getMaxWidth(lines.stream().map(TextLine::text).collect(Collectors.toList()))+2;
        printCutoffLine(appender, maxWidth);

        for (TextLine line: lines) {
            String lineText = line.text() == null ? "" : line.text();
            appender.append(String.format("| %s%s |\n", lineText, "                                                                                  ".substring(0,maxWidth-lineText.length())));
        }
        printCutoffLine(appender, maxWidth);
    }

    public void printResult(Result result) {
        appender.append("\n");
        appender.append("\n");
        appender.append("\n");

        if (result!=null) {
            appender.append(result.toString());
        } else {
            appender.append("No PaymentResult received\n");
        }
    }

    public void printResultState(ResultState resultState){
        appender.append("\n");
        appender.append("\n");
        appender.append("\n");

        if(resultState!=null){
            appender.append(resultState.name());
        } else {
            appender.append("No ResultState received\n");
        }
    }

    public void printError(MAPIError error){
        appender.append("\n");
        appender.append("\n");
        appender.append("\n");

        if(error != null){
            appender.append("The next error occured: "+error.name());
        } else {
            appender.append("No error received");
        }
    }

    public void print(String result){
        appender.append("\n");
        appender.append("\n");
        appender.append("\n");

        if(result != null){
            appender.append(result);
        } else {
            appender.append("No result received\n");
        }
    }

    private void printCutoffLine(OutputAppender console, int maxWidth) {
        console.append("\n");
        console.append("\n");
        console.append("\n");
        console.append(" ");
        for (int i=0; i<=maxWidth; i+=2) {
            console.append("/\\");
        }
        console.append("\n");
        console.append("\n");
        console.append("\n");
    }

    private int getMaxWidth(List<String> lines) {
        int maxWidth=0;
        for (String line : lines) {
            if (StringUtils.isNotEmpty(line) && line.length()>maxWidth) {
                maxWidth = line.length();
            }
        }
        return maxWidth;
    }
}
