package com.pwt.netty.common.chargerold;

import com.pwt.netty.common.chargerold.client.*;
import com.pwt.netty.common.chargerold.server.*;

import java.util.function.Predicate;

/**
 * @author linyun
 * @version V1.0
 * @Title: OperationType
 * @Description: 操作类型
 * @date 2022/11/15
 **/
public enum OperationType {

    ChargerChargeStatus(0X10, ChargerChargeStatusData.class, ChargerChargeStatusResponseData.class),
    BatteryStatus(0X11,BatteryStatusData.class, BatteryStatusResponseData.class),
    BatteryFault(0X12,BatteryFaultData.class, BatteryFaultResponseData.class),
    BmsStatus(0X13,BmsStatusData.class, BmsStatusResponseData.class),
    BatteryOther(0X14, BatteryOtherData.class, BatteryOtherResponseData.class),
    ChargerStatus(0x15, ChargerStatusData.class, ChargerStatusResponseData.class),
    ChargeComplete(0X20, ChargeCompleteData.class, ChargeCompleteResponseData.class),
    ChargerAlarm(0X30, ChargerAlarmData.class, ChargerAlarmResponseData.class),
    StartStop(0X50, StartStopData.class, StartStopResponseData.class),
    Configuration(0X70, ConfigurationCmdData.class, ConfigurationCmdResponseData.class),
    ControlLamp(0X80, ControlLampData.class, ControlLampResponseData.class),
    InspectionTime(0X90, InspectionTimeData.class, InspectionTimeResponseData.class);

    private final int opCode;
    private final Class<? extends RequestData> requestDataClazz;
    private final Class<? extends ResponseData> responseDataClazz;


    OperationType(int opCode, Class<? extends RequestData> requestDataClazz, Class<? extends ResponseData> responseDataClazz) {
        this.opCode = opCode;
        this.requestDataClazz = requestDataClazz;
        this.responseDataClazz = responseDataClazz;
    }

    public int getOpCode(){
        return opCode;
    }

    public Class<? extends RequestData> getRequestClazz() {
        return requestDataClazz;
    }

    public Class<? extends ResponseData> getResponseClazz() {
        return responseDataClazz;
    }


    public static OperationType fromOpCode(int type){
        return getOperationType(requestType -> requestType.opCode == type);
    }

    public static OperationType fromRequest(RequestData request){
        return getOperationType(requestType -> requestType.requestDataClazz == request.getClass());
    }

    public static OperationType fromResponse(ResponseData response ){
        return getOperationType(requestType -> requestType.responseDataClazz == response.getClass());
    }
    private static OperationType getOperationType(Predicate<OperationType> predicate){
        OperationType[] values = values();
        for (OperationType operationType : values) {
            if(predicate.test(operationType)){
                return operationType;
            }
        }

        throw new AssertionError("no found type");
    }
}
