package com.pwt.netty.common.vehicle2old;


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

import java.util.function.Predicate;

public enum OperationType {
    /***
     * 度电数据
     */
    Power(0x01, PowerData.class, PowerResponseData.class),
    HeartBeat(0X03, HeartBeatData.class, HeartBeatResponseData.class),
    Luck(0X05, LockData.class, LockResponseData.class),
    UnLock(0X07, UnLockData.class, UnLockResponseData.class),
    SettlementConfirm(0X09, SettlementConfirmData.class, SettlementComfirmResponseData.class),
    SetParameters(0X11, SetParametersData.class, SetParametersResponseData.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");
    }
}
