package pl.polgrabia.demos.crackingcodeinterview.t16x8;

import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

public class EnNumberDescriptionProcessor implements NumberDescriptionProcessor {

    private static final List<String> descriptions = new LinkedList<>();
    private final Properties properties;

    public EnNumberDescriptionProcessor() {
        try (InputStream is = getI18nDataInputStream()) {
            this.properties = loadProperties(is);
        } catch (IOException e) {
            throw new IllegalStateException("Couldn't load stream", e);
        }
    }

    private InputStream getI18nDataInputStream() throws FileNotFoundException {
        String enLocation = System.getProperty("numbers.descriptions.en.location");
        InputStream is;
        if (enLocation != null) {
            is = new FileInputStream(enLocation);
        } else {
            is = getClass().getClassLoader().getResourceAsStream("numbers.properties");
        }
        return is;
    }

    private Properties loadProperties(InputStream is) throws IOException {
        var properties = new Properties();
        try (is) {
            properties.load(is);
            return properties;
        } catch (IOException e) {
            throw new IllegalStateException("Couldn't load from stream", e);
        }
    }

    private String dump_thousand(int t) {
        var x1 = t % 10;
        var x2 = (t / 10) % 10;
        var x3 = (t / 100) % 10;
        List<String> parts = new ArrayList<>();
        if (x3 > 0) {
            parts.add(getNumberDescription(x3) + " " + getNumberDescription(100));
        }
        if (x2 > 0) {
            parts.add(getNumberDescription(x2 * 10));
        }
        if (x1 > 0) {
            parts.add(getNumberDescription(x1));
        }
        return String.join(" ", parts);
    }

    private String getNumberDescription(int nr) {
        return properties.getProperty("numbers.descriptions." + nr);
    }

    @Override
    public void process(int nr, PrintStream ps) {
        int index = 1;
        while (nr > 0) {
            var t = nr % 1000;
            String groupDescription = dump_thousand(t);
            if (t > 0 && index > 1) {
                groupDescription += " " + getNumberDescription(index) + (t > 1 ? "S" : "");
            }
            descriptions.add(groupDescription);

            nr /= 1000;
            index *= 1000;
        }

        ps.println(String.join(" ", descriptions.reversed()));
    }
}
