package com.gingersoft.gsa.cloud.common.config.expandconfig;

import com.gingersoft.gsa.cloud.common.Api;
import com.gingersoft.gsa.cloud.common.utils.JsonUtils;
import com.gingersoft.gsa.cloud.common.utils.ReflectionUtils;
import com.gingersoft.gsa.cloud.common.core.restaurant.utils.RestaurantExpandInfoUtils;
import com.gingersoft.gsa.cloud.common.utils.okhttpUtils.OkHttp3Utils;
import com.gingersoft.gsa.cloud.common.constans.HttpsConstans;
import com.gingersoft.gsa.cloud.database.bean.ExpandInfo;
import com.gingersoft.gsa.cloud.database.utils.ExpandInfoDaoUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import okhttp3.MediaType;
import okhttp3.RequestBody;

import static com.gingersoft.gsa.cloud.app.GsaCloudApplication.getAppContext;

/**
 * @author : bin
 * @create date: 2020-10-20
 * @update date: 2020-10-20
 * @description:
 */

@Builder
@Getter
@Setter
public class ExpandInfoSetting {
    private String settingName;
    private Integer valueInt;
    private String valueChar;
    private Boolean valueBoolean;
    private String valueDateTime;
    /**
     * 數據類型 1：整形，2：字符型，3：布爾型，4：日期類型
     */
    private int dataType;
    private int sort;
    private String showName;
    private String remark;


    public <T> T getValue() {
        if (valueChar != null) {
            return (T) valueChar;
        } else if (valueBoolean != null) {
            return (T) valueBoolean;
        } else if (valueDateTime != null) {
            return (T) valueDateTime;
        } else if (valueInt != null) {
            return (T) valueInt;
        }
        return null;
    }

    public static void initUpdateExtendedConfiguration(Object... objects) {
        Observable.just(0)
                .subscribeOn(Schedulers.io())
                .subscribe(integer -> {
                    List<ExpandInfoSetting> expandInfoSettingList = new ArrayList<>();

                    for (Object obj : objects) {
                        expandInfoSettingList.addAll(scanExtendedConfiguration(obj));
                    }

                    String expandInfoListJson = JsonUtils.toJson(expandInfoSettingList);
                    RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), expandInfoListJson);

                    OkHttp3Utils.post(HttpsConstans.ROOT_SERVER_ADDRESS_FORMAL + Api.add_restaurant_base_table_configuration, requestBody)
                            .subscribe(new Observer<String>() {

                                @Override
                                public void onSubscribe(Disposable d) {

                                }

                                @Override
                                public void onNext(String s) {

                                }

                                @Override
                                public void onError(Throwable e) {
                                }

                                @Override
                                public void onComplete() {
                                    //從本地獲取餐廳擴展表數據
                                    ExpandInfoDaoUtils expandInfoDaoUtils = new ExpandInfoDaoUtils(getAppContext());
                                    List<ExpandInfo> expandInfos = expandInfoDaoUtils.queryAllExpandInfo();
                                    if (expandInfos != null) {
                                        RestaurantExpandInfoUtils.setCommonExpandInfo(expandInfos);
                                    }
                                }
                            });
                });
    }


    /**
     * 掃描獲取擴展類信息
     * @param obj
     * @return
     */
    private static List<ExpandInfoSetting> scanExtendedConfiguration(Object obj) {

        List<ExpandInfoSetting> expandInfoList = new ArrayList<>();

        HashMap<String, String> settingNameMap = new HashMap<>();

        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            settingNameMap.put(field.getName().substring(1), field.getName());
        }

        Method[] methods = obj.getClass().getDeclaredMethods();

        for (Method method : methods) {
            Class<?> returnClass = method.getReturnType();
            if (method.getName().startsWith("get") && returnClass.equals(ExpandInfoSetting.class)) {
                try {
                    Object[] objs = {};
                    //反射執行get方法 獲取每個配置類信息
                    ExpandInfoSetting expandInfo = (ExpandInfoSetting) ReflectionUtils.invokeMethod(method, obj, objs);
                    //獲取完整的settingName
                    String settingName;
                    if (settingNameMap.containsKey(method.getName().substring(4))) {
                        settingName = settingNameMap.get(method.getName().substring(4));
                    } else {
                        settingName = method.getName().substring(3);
                    }
                    expandInfo.setSettingName(settingName);
                    expandInfo.setShowName(settingName);
                    if (expandInfo.getValueInt() != null) {
                        expandInfo.setDataType(ExpandInfo.data_type_int);
                    } else if (expandInfo.getValueChar() != null) {
                        expandInfo.setDataType(ExpandInfo.data_type_string);
                    } else if (expandInfo.getValueBoolean() != null) {
                        expandInfo.setDataType(ExpandInfo.data_type_boolean);
                    } else if (expandInfo.getValueDateTime() != null) {
                        expandInfo.setDataType(ExpandInfo.data_type_date);
                    }
                    if (expandInfo.getValueInt() == null) {
                        //為了兼容後台，這裡不是valueInt值默認給0
                        expandInfo.setValueInt(0);
                    }
                    expandInfoList.add(expandInfo);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
        return expandInfoList;
    }
}

