package com.yanzuoguang.util.base;

import com.yanzuoguang.util.helper.StringHelper;

import java.util.*;

/**
 * 集合转换为表格字符串
 *
 * @author 颜佐光
 */
public class CollectionString {
    private static final String SPLIT = "|";
    private static final String EMPTY = " ";
    private static final String ROW = "-";
    private static final int EMPTY_SIZE = 2;

    /**
     * 集合转换为表格字符串
     *
     * @param rowList 需要转换的集合
     * @param <T>     集合类型
     * @return 表格字符串
     */
    public static <T> String getCollectionString(String tag, Collection<T> rowList) {
        // 每个字段的长度
        Map<String, Integer> mapFieldCount = getValueLength(rowList);
        // 删除为0的长度,并将列名长度写入
        initColumnNameLength(mapFieldCount);
        // 生成结果
        StringBuilder sbResult = new StringBuilder();
        sbResult.append(tag);
        appendEmptyRow(sbResult, mapFieldCount);
        sbResult.append(System.lineSeparator());
        sbResult.append(SPLIT);
        mapFieldCount.forEach((name, len) -> {
            int nameLen = length(name);
            appendChar(sbResult, EMPTY_SIZE, EMPTY);
            sbResult.append(name);
            appendChar(sbResult, len - nameLen + EMPTY_SIZE, EMPTY);
            sbResult.append(SPLIT);
        });
        appendEmptyRow(sbResult, mapFieldCount);
        // 遍历每一行
        rowList.forEach(row -> {
            sbResult.append(System.lineSeparator());
            sbResult.append(SPLIT);
            mapFieldCount.forEach((name, len) -> {
                appendChar(sbResult, EMPTY_SIZE, EMPTY);
                // 获取字符串
                String value = StringHelper.getFirst(ObjectHelper.getString(row, name));
                sbResult.append(value);
                appendChar(sbResult, len - length(value) + EMPTY_SIZE, EMPTY);
                sbResult.append(SPLIT);
            });
        });
        appendEmptyRow(sbResult, mapFieldCount);
        return sbResult.toString();
    }

    /**
     * 获取值字段的长度
     *
     * @param rowList 行
     * @param <T>     行类型
     * @return 各列值长度
     */
    private static <T> Map<String, Integer> getValueLength(Collection<T> rowList) {
        // 每个字段的长度
        Map<String, Integer> mapFieldCount = new LinkedHashMap<>(15);
        // 每个值的长度
        rowList.forEach(row -> ObjectEach.each(row, (rowFieldName, rowFieldValue, rowFieldInfo) -> {
            // 获取字符串
            String val = StringHelper.getFirst(StringHelper.toString(rowFieldValue));
            int len = length(val);
            Integer hisLen = mapFieldCount.getOrDefault(rowFieldName, len);
            int maxLen = Math.max(len, hisLen);
            mapFieldCount.put(rowFieldName, maxLen);
        }));
        return mapFieldCount;
    }

    /**
     * 删除为0的长度,并将列名长度写入
     *
     * @param mapFieldCount
     */
    private static void initColumnNameLength(Map<String, Integer> mapFieldCount) {
        // 添加到另外一个集合,防止遍历列名通知执行删除时出错
        List<String> keys = new ArrayList<>(mapFieldCount.keySet());
        keys.forEach(key -> {
            int len = mapFieldCount.get(key);
            if (len == 0) {
                mapFieldCount.remove(key);
            } else {
                int maxLen = Math.max(len, length(key));
                mapFieldCount.put(key, maxLen);
            }
        });
    }

    /**
     * 添加空行
     *
     * @param sbResult
     * @param mapFieldCount
     */
    private static void appendEmptyRow(StringBuilder sbResult, Map<String, Integer> mapFieldCount) {
        if (sbResult.length() > 0) {
            sbResult.append(System.lineSeparator());
        }
        sbResult.append(SPLIT);
        mapFieldCount.forEach((name, len) -> {
            appendChar(sbResult, len + EMPTY_SIZE + EMPTY_SIZE, ROW);
            sbResult.append(SPLIT);
        });
    }

    /**
     * 添加字符
     *
     * @param sb  字符串
     * @param len 长度
     * @param ch  字符
     */
    private static void appendChar(StringBuilder sb, int len, String ch) {
        for (int i = 0; i < len; i++) {
            sb.append(ch);
        }
    }

    /**
     * 获取字符串的长度,如果有中⽂,则每个中⽂字符计为2位
     *
     * @param value 指定的字符串
     * @return 字符串的长度
     */
    public static int length(String value) {
        int chLength = 0;
        int enLength = 0;
        String chinese = "[\u0391-\uFFE5]";
        /* 获取字段值的长度,如果含中⽂字符,则每个中⽂字符长度为2,否则为1 */
        for (int i = 0; i < value.length(); i++) {
            /* 获取⼀个字符 */
            String temp = value.substring(i, i + 1);
            /* 判断是否为中⽂字符 */
            if (temp.matches(chinese)) {
                /* 中⽂字符长度为2 */
                chLength++;
            } else {
                /* 其他字符长度为1 */
                enLength++;
            }
        }
        return chLength * 5 / 3 + enLength;
    }
}