package com.sckw.excel.translate;


import com.sckw.core.common.enums.NumberConstant;
import com.sckw.core.exception.SourceInitializeException;
import com.sckw.core.exception.TranslateException;
import com.sckw.excel.translate.annotation.Translate;
import com.sckw.excel.translate.annotation.Translates;
import com.sckw.excel.translate.enums.Source;
import com.sckw.excel.translate.wrapper.AbstractTranslator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

import java.util.*;

/**
 *
 * 处理翻译字段
 *
 *
 * @author lfdc
 * @version v1
 * @create 2020-11-28 15:17:54
 * @copyright
 */
@Slf4j
public class Translator extends AbstractTranslator {



    /**
     * 对某个参数值进行翻译 传入编码或者ID并指定数据源
     * 如果传入的编码值没有匹配的数据会返回NULL
     *
     * @param code 参数编码值
     * @param source 数据源{@see com.***.g3.common.translate.enums.Source}
     * @return 翻译后的值
     * @throws TranslateException 初始化数据源失败时抛出异常
     */
    @Nullable
    public static Object translate(Integer code, Source source) {
        try {
            return SourceUtil.get(source).get(code);
        } catch (Exception e) {
            throw new TranslateException("translation failed. ex:" + e.toString(), e);
        }
    }

    /**
     * 对多个参数值进行翻译 传入编码或者ID的集合并指定数据源
     * 如果传入的编码值没有匹配的数据会返回原始值
     *
     * @param codes  参数编码值 list
     * @param source 数据源 {@see com.owinfo.mpw.common.translate.enums.Source}
     * @return 翻译后的值
     * @throws TranslateException 初始化数据源失败时抛出异常
     */
    @Nullable
    public static List<Integer> translate(List<Integer> codes, Source source) {
        try {
            Map<Integer, Object> sources = SourceUtil.get(source);
            List<Integer> result = new ArrayList<>(codes.size());
            for (Integer code : codes) {
                Object target = sources.get(code);
                if (target == null) {
                    log.warn("the target value of the translation is null, fieldValue -> {}", code);
                    result.add(code);
                } else {
//                    result.add(target.toString());
                    result.add((Integer) target);
                }
            }
            return result;
        } catch (Exception e) {
            throw new TranslateException("translation failed. ex:" + e.toString(), e);
        }
    }

    /**
     * 对集合中所有的实体进行翻译
     * 需要在实体中使用 {@link Translates} 或者 {@link Translate} 指定需要翻译的字段
     * 指定后当前集合都会按照配置的字段列表进行翻译所有实体
     *
     * @param list 需要翻译的源实体 不能为空
     * @throws TranslateException 初始化数据源失败时抛出异常
     */
    public static void translate(List list) {
        try {
            Assert.isTrue(list != null && list.size() > NumberConstant.ZERO, "the data source cannot be empty");
            Translates translates = list.get(0).getClass().getAnnotation(Translates.class);
            if (translates != null && translates.value().length > NumberConstant.ZERO) {
                translate(Arrays.asList(translates.value()), list, getSources());
                return;
            }
            Translate translate = list.get(0).getClass().getAnnotation(Translate.class);
            if (translate != null) {
                translate(Collections.singletonList(translate), list, getSources());
                return;
            }
            throw new IllegalArgumentException("must specify @Translates or @Translate");
        } catch (Exception e) {
            if (e instanceof TranslateException) {
                throw (TranslateException) e;
            }
            throw new TranslateException("translation failed. ex:" + e.toString(), e);
        }
    }

    public static Map<Source, Map<Integer, Object>> getSources() throws SourceInitializeException {
        Map<Source, Map<Integer, Object>> sources = new HashMap<>(2);
        //sources.put(Source.DICTIONARY, SourceUtil.get(Source.DICTIONARY));
//        sources.put(Source.ORGANIZATION, SourceUtil.get(Source.ORGANIZATION));
        sources.put(Source.ENUMS, SourceUtil.get(Source.ENUMS));
        return sources;
    }
}