import java.io.*;
import java.util.*;

public class Euler22 {

    private static class Options {
        String namesFile = "resources/documents/0022_names.txt";
        boolean runCheckpoints = true;
    }

    private static boolean parseStringAfterPrefix(String arg, String prefix, StringBuilder value) {
        if (!arg.startsWith(prefix)) {
            return false;
        }
        String tail = arg.substring(prefix.length());
        if (tail.isEmpty()) {
            return false;
        }
        value.setLength(0);
        value.append(tail);
        return true;
    }

    private static boolean parseArguments(String[] args, Options options) {
        for (String arg : args) {
            if (arg.equals("--skip-checkpoints")) {
                options.runCheckpoints = false;
                continue;
            }
            StringBuilder value = new StringBuilder();
            if (parseStringAfterPrefix(arg, "--names-file=", value)) {
                options.namesFile = value.toString();
                continue;
            }
            System.err.println("Unknown argument: " + arg);
            return false;
        }
        return true;
    }

    private static List<String> parseCsvNames(String payload) {
        List<String> names = new ArrayList<>();
        StringBuilder current = new StringBuilder();
        boolean insideQuotes = false;

        for (char ch : payload.toCharArray()) {
            if (ch == '"') {
                insideQuotes = !insideQuotes;
                if (!insideQuotes) {
                    names.add(current.toString());
                    current.setLength(0);
                }
                continue;
            }
            if (insideQuotes) {
                current.append(ch);
            }
        }

        return names;
    }

    private static long nameValue(String name) {
        long value = 0;
        for (char c : name.toCharArray()) {
            if (c >= 'A' && c <= 'Z') {
                value += (c - 'A' + 1);
            }
        }
        return value;
    }

    private static long scoreSum(List<String> names) {
        Collections.sort(names);

        long total = 0;
        for (int i = 0; i < names.size(); i++) {
            long position = (long)(i + 1);
            total += position * nameValue(names.get(i));
        }
        return total;
    }

    private static long solve(String namesFile) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(namesFile));
        StringBuilder buffer = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            buffer.append(line);
        }
        reader.close();

        return scoreSum(parseCsvNames(buffer.toString()));
    }

    private static boolean runCheckpoints() {
        if (nameValue("COLIN") != 53) {
            System.err.println("Checkpoint failed for COLIN value");
            return false;
        }

        List<String> sample = Arrays.asList("B", "A");
        if (scoreSum(sample) != 5) {
            System.err.println("Checkpoint failed for small score set");
            return false;
        }

        return true;
    }

    public static void main(String[] args) {
        Options options = new Options();
        if (!parseArguments(args, options)) {
            System.exit(1);
        }

        if (options.runCheckpoints && !runCheckpoints()) {
            System.exit(2);
        }

        try {
            System.out.println(solve(options.namesFile));
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
            System.exit(3);
        }
    }
}
