// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
package com.ibm.icu.dev.test.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import com.ibm.icu.dev.test.AbstractTestLog;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.dev.util.CollectionUtilities;
import com.ibm.icu.impl.locale.XCldrStub.FileUtilities;
import com.ibm.icu.impl.locale.XCldrStub.Splitter;
import com.ibm.icu.util.ICUUncheckedIOException;

abstract public class DataDrivenTestHelper {

    public static final List<String> DEBUG_LINE = Collections.singletonList("@debug");
    public static final Splitter SEMICOLON = Splitter.on(';').trimResults();
    public static final Splitter EQUAL_SPLIT = Splitter.on('=').trimResults();
    public static final String SEPARATOR = " ; \t";

    protected TestFmwk framework = null;
    protected int minArgumentCount = 3;
    protected int maxArgumentCount = 4;
    private List<List<String>> lines = new ArrayList<>();
    private List<String> comments = new ArrayList<>();

    public DataDrivenTestHelper setFramework(TestFmwk testFramework) {
        this.framework = testFramework;
        return this;
    }

    public <T extends Appendable> T appendLines(T out) {
        try {
            for (int i = 0; i < lines.size(); ++i) {
                List<String> components = lines.get(i);
                String comment = comments.get(i);
                if (components.isEmpty()) {
                    if(!comment.isEmpty()) {
                        out.append("# ").append(comment);
                    }
                } else {
                    String first = components.iterator().next();
                    String sep = first.startsWith("@") ? "=" : SEPARATOR;
                    out.append(CollectionUtilities.join(components, sep));
                    if (!comment.isEmpty()) {
                        out.append("\t# ").append(comment);
                    }
                }
                out.append('\n');
            }
            return out;
        } catch (IOException e) {
            throw new ICUUncheckedIOException(e);
        }
    }

    protected DataDrivenTestHelper addLine(List<String> arguments, String commentBase) {
        lines.add(Collections.unmodifiableList(arguments));
        comments.add(commentBase);
        return this;
    }

    public DataDrivenTestHelper run(Class<?> classFileIsRelativeTo, String file) {
        return load(classFileIsRelativeTo, file)
            .test();
    }

    public boolean isTestLine(List<String> arguments) {
        return !arguments.isEmpty() && !arguments.equals(DEBUG_LINE);
    }

    public DataDrivenTestHelper test() {
        boolean breakpoint = false;
        for (int i = 0; i < lines.size(); ++i) {
            List<String> arguments = lines.get(i);
            String comment = comments.get(i);
            if (arguments.isEmpty()) {
                if (!comment.isEmpty()) {
                    AbstractTestLog.logln(comment);
                }
                continue;
            } else if (arguments.equals(DEBUG_LINE)) {
                breakpoint = true;
                continue;
            } else {
                String first = arguments.get(0);
                if (first.startsWith("@")) {
                    handleParams(comment, arguments);
                    continue;
                }
            }
            try {
                handle(i, breakpoint, comment, arguments);
            } catch (Exception e) {
                e.printStackTrace();
                AbstractTestLog.errln("Illegal data test file entry (" + i + "): " + arguments + " # " + comment);
            }
            breakpoint = false;
        }
        return this;
    }

    public DataDrivenTestHelper load(Class<?> classFileIsRelativeTo, String file) {
        BufferedReader in = null;
        try {
            in = FileUtilities.openFile(classFileIsRelativeTo, file);
            //boolean breakpoint = false;

            while (true) {
                String line = in.readLine();
                if (line == null) {
                    break;
                }
                line = line.trim();
                if (line.isEmpty()) {
                    addLine(Collections.<String>emptyList(), "");
                    continue;
                }
                int hash = line.indexOf('#');
                String comment = "";
                String commentBase = "";
                if (hash >= 0) {
                    commentBase = line.substring(hash+1).trim();
                    line = line.substring(0,hash).trim();
                    comment = "# " + commentBase;
                    if (!line.isEmpty()) {
                        comment = "\t" + comment;
                    }
                }
                if (line.isEmpty()) {
                    addLine(Collections.<String>emptyList(), commentBase);
                    continue;
                }
                if (line.startsWith("@")) {
                    List<String> keyValue = EQUAL_SPLIT.splitToList(line);
                    addLine(keyValue, comment);
                    continue;
                }
                List<String> arguments = SEMICOLON.splitToList(line);
                if (arguments.size() < minArgumentCount || arguments.size() > maxArgumentCount) {
                    AbstractTestLog.errln("Malformed data line:" + line + comment);
                    continue;
                }
                addLine(arguments, commentBase);
            }
        } catch (IOException e) {
            throw new ICUUncheckedIOException(e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    throw new ICUUncheckedIOException(e);
                }
            }
        }
        lines = Collections.unmodifiableList(lines); // should do deep unmodifiable...
        comments = Collections.unmodifiableList(comments);
        return this;
    }

    protected boolean assertEquals(String message, Object expected, Object actual) {
        return TestFmwk.handleAssert(Objects.equals(expected, actual), message, stringFor(expected), stringFor(actual), null, false);
    }

    private final String stringFor(Object obj) {
        return obj == null ? "null"
            : obj instanceof String ? "\"" + obj + '"'
                : obj instanceof Number ? String.valueOf(obj)
                    : obj.getClass().getName() + "<" + obj + ">";
    }

    abstract public void handle(int lineNumber, boolean breakpoint, String commentBase, List<String> arguments);

    public void handleParams(String comment, List<String> arguments) {
        throw new IllegalArgumentException("Unrecognized parameter: " + arguments);
    }

    public List<List<String>> getLines() {
        return lines;
    }
}