package com.on_site.kamayan;

import com.google.common.base.Joiner;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class Kamayan {
    private Kamayan() {}

    public static <T> T getField(Object object, Class<T> expectedReturnType, String fieldName) {
        try {
            Field field = object.getClass().getField(fieldName);
            field.setAccessible(true);
            return expectedReturnType.cast(field.get(object));
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void setField(Object object, String fieldName, Object value) {
        try {
            Field field = object.getClass().getField(fieldName);
            field.setAccessible(true);
            field.set(object, value);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void times(int n, Consumer<Integer> fn) {
        range(0, n - 1, fn);
    }

    public static void range(int start, int end, Consumer<Integer> fn) {
        for (int i = start; i <= end; i++) {
            fn.accept(i);
        }
    }

    public static String wrap(String str, int length) {
        List<String> lines = new ArrayList<>();

        while (str.length() > length) {
            if (str.indexOf(' ') < 0) {
                lines.add(str);
                str = "";
            } else if (str.indexOf(' ') > length) {
                lines.add(str.substring(0, str.indexOf(' ')));
                str = str.substring(str.indexOf(' ') + 1);
            } else {
                int index = str.substring(0, length + 1).lastIndexOf(' ');
                lines.add(str.substring(0, index));
                str = str.substring(index + 1);
            }
        }

        if (!str.isEmpty()) {
            lines.add(str);
        }

        return Joiner.on("\n").join(lines);
    }

    public static TodoException todo(String... lines) {
        for (int i = 0; i < lines.length; i++) {
            if (lines[i].equals("")) {
                lines[i] = "\n\n";
            }
        }

        String[] paragraphs = ("TODO:\n" + Joiner.on(" ").join(lines)).replaceAll("(?m)^ +", "").replaceAll("(?m) +$", "").split("\n");

        for (int i = 0; i < paragraphs.length; i++) {
            paragraphs[i] = wrap(paragraphs[i], 80);
        }

        throw new TodoException(Joiner.on("\n").join(paragraphs));
    }
}

@@ -360,32 +360,41 @@
   Field field = 
+getField(
 object.getClass(
@@ -390,34 +390,26 @@
 t.getClass()
-.getField(
+, 
 fieldName);%0A
@@ -783,16 +783,25 @@
 field = 
+getField(
 object.g
@@ -813,18 +813,10 @@
 ss()
-.getField(
+, 
 fiel
@@ -984,32 +984,32 @@
 (Exception e) %7B%0A
-
             thro
@@ -1044,32 +1044,711 @@
        %7D%0A    %7D%0A%0A
+    private static Field getField(Class%3C?%3E clazz, String fieldName) throws NoSuchFieldException %7B%0A        try %7B%0A            return clazz.getField(fieldName);%0A        %7D catch (NoSuchFieldException e) %7B%0A            return getDeclaredField(clazz, fieldName);%0A        %7D%0A    %7D%0A%0A    private static Field getDeclaredField(Class%3C?%3E clazz, String fieldName) throws NoSuchFieldException %7B%0A        try %7B%0A            return clazz.getDeclaredField(fieldName);%0A        %7D catch (NoSuchFieldException e) %7B%0A            clazz = clazz.getSuperclass();%0A%0A            if (clazz == null) %7B%0A                throw e;%0A            %7D%0A%0A            return getDeclaredField(clazz, fieldName);%0A        %7D%0A    %7D%0A%0A
     public stati

Fix getField to work for private fields