package com.sckw.excel.translate.wrapper;


import com.sckw.core.common.enums.NumberConstant;
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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 *
 * 翻译器的抽象类
 *
 *
 * @author lfdc
 * @version v1
 * @create 2021-03-31 11:28:25
 * @copyright
 */
@Slf4j
public abstract class AbstractTranslator {


    protected static void translate(List<Translate> translates, List list, Map<Source, Map<Integer, Object>> sources) {
        for (Object obj : list) {
            translate(translates, obj, sources);
        }
    }

    protected static List<Translate> getTranslates(Method method) {
        Translates translates = method.getAnnotation(Translates.class);
        if (translates != null && translates.value().length > NumberConstant.ZERO) {
            return Arrays.asList(translates.value());
        }
        return Collections.singletonList(method.getAnnotation(Translate.class));
    }

    @SuppressWarnings("unchecked")
    protected static void translate(List<Translate> translates, Object obj, Map<Source, Map<Integer, Object>> sources) {
        Class<?> clazz = obj.getClass();
        for (Translate translate : translates) {
            try {
                Field field;
                try {
                    field = clazz.getDeclaredField(translate.field());
                } catch (NoSuchFieldException e) {
                    //try to get from the super class
                    if (clazz.getSuperclass() != null) {
                        field = clazz.getSuperclass().getDeclaredField(translate.field());
                    } else {
                        throw e;
                    }
                }

                Assert.notNull(field, "the field specified by @Translate cannot be matched in the returned entity, field -> " + translate.field());
                field.setAccessible(true);
                if (translate.isArray()) {
                    translate(translates, (List) field.get(obj), sources);
                } else if (translate.isString()) {
                    Map<Integer, Object> source = sources.get(translate.source());
                    Object fieldVal = field.get(obj);
                    if (fieldVal == null || StringUtils.isEmpty(fieldVal.toString())) {
                        continue;
                    }
                    Object target = source.get(fieldVal);
                    if (target != null) {
                        field.set(obj, target);
                    } else {
                        log.warn("the target value of the translation is null, fieldValue -> {}", fieldVal);
                    }
                }
            } catch (Exception e) {
                throw new TranslateException("translation failed. Processing error, " + e.toString());
            }
        }
    }
}