package util;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Map;
import java.util.Scanner;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;

public class Toolset {
    public static int option() {
        Scanner reader = new Scanner(System.in);
        int chose;
        //读取选项
        while (true) {
            if (reader.hasNextInt()) {
                chose = reader.nextInt();
                break;
            } else {
                System.out.println("你的输入有误，请重新输入~");
            }
        }
        return chose;
    }

    //shellUI格式化输出
    private static final Map<Class<?>, Field[]> CLASS_2_FIELD_NAME = new ConcurrentHashMap<>();

    /**
     * 将对象打印成表格
     */
    @SafeVarargs
    public static <T> String table(Class<T> clazz, T... objs) throws IllegalAccessException {
        Field[] fields = safeGetRefCtx(clazz);
        if (fields.length == 0) {
            return "";
        }
        // 计算每一列
        int[] maxLens = new int[fields.length];
        for (int i = 0; i < fields.length; i++) {
            final int ti = i;
            // 取出当前字段中最长的长度
            maxLens[i] = Arrays.stream(objs)
                    .map(item -> {
                        try {
                            return String.valueOf(fields[ti].get(item));
                        } catch (IllegalAccessException e) {
                            // pass
                        }
                        return "";
                    })
                    .mapToInt(String::length)
                    .max()
                    .orElse(0);
        }
        StringJoiner result = new StringJoiner("\n");
        for (T obj : objs) {
            // 竖线前后加一个空格分割
            StringJoiner sj = new StringJoiner(" | ");
            for (int i = 0; i < fields.length; i++) {
                sj.add(fields[i].getName() + ": " + padRight(String.valueOf(fields[i].get(obj)), maxLens[i]));
            }
            result.merge(sj);
        }
        return result.toString();
    }

    /**
     * 右侧补充字符
     */
    @Contract(pure = true)
    private static @NotNull String padRight(@NotNull String origin, int length) {
        StringBuilder originBuilder = new StringBuilder(origin);
        while (originBuilder.length() < length) {
            originBuilder.append(' ');
        }
        origin = originBuilder.toString();
        return origin;
    }

    private static Field @NotNull [] safeGetRefCtx(Class<?> clazz) {
        Field[] fields = CLASS_2_FIELD_NAME.get(clazz);
        if (fields == null) {
            fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                //打开私有访问
                field.setAccessible(true);
            }
            CLASS_2_FIELD_NAME.put(clazz, fields);
        }
        return fields;
    }

}
