package ch.zhaw.ads;

import java.lang.ArrayIndexOutOfBoundsException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class BinaryTreeRankingServer implements CommandExecutor {
    SortedBinaryTree<Competitor> competitors;
    int startingRank;
    StringBuffer result;

    @Override
    public String execute(String input) {
        this.competitors = parseCSV(input);

        result = new StringBuffer(100);
        startingRank = 1;
        result.append("\n\nSorted Competitors (by time):\n");
        competitors.traversal().inorder(visitor);

        return result.toString();
    }

    // This works only because of
    // https://stackoverflow.com/questions/29029849/why-do-java-8-lambdas-allow-access-to-non-final-class-variables
    Visitor<Competitor> visitor = competitor -> {
        competitor.setRank(startingRank++);
        result.append(competitor.toString() + "\n");
    };

    /**
     * NOTE ABOUT CSV FORMAT (from `man virt-diff`)
     *        Comma-separated values (CSV) is a deceptive format.  It seems like it should be easy to parse,
     *        but it is definitely not easy to parse.
     *
     *        Myth: Just split fields at commas.  Reality: This does not work reliably.  This example has two
     *        columns:
     *
     *         "foo,bar",baz
     *
     *        Myth: Read the file one line at a time.  Reality: This does not work reliably.  This example has
     *        one row:
     *
     *         "foo
     *         bar",baz
     */
    private SortedBinaryTree<Competitor> parseCSV(String csv) {
        int startNr, jg;
        String name, country, time;

        SortedBinaryTree<Competitor> competitors = new SortedBinaryTree<Competitor>();
        for (String record : csv.split("\\r?\\n")) {
            String[] values = record.split(";");

            try {
                startNr = Integer.valueOf(values[0]);
                name = values[1];
                jg = Integer.valueOf(values[2]);
                country = values[3];
                time = values[4];
                competitors.add(new Competitor(startNr, name, jg, country, time));
            } catch (NumberFormatException | ParseException | ArrayIndexOutOfBoundsException e) {
                System.err.println("Failed to add competitor.");
                continue;
            }
        }
        return competitors;
    }

    public Tree getTree() {
        return competitors;
    }
}
