package com.airlock.iam.flow.infrastructure.serialization;

import com.airlock.iam.flow.domain.model.event.StateMachineFlowEvent;
import com.airlock.iam.flow.domain.model.statemachine.FlowState;
import com.airlock.iam.flow.domain.model.statemachine.runtime.FlowStateWithStep;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import jakarta.inject.Inject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.stream.Stream;
import lombok.NonNull;
import org.springframework.statemachine.StateMachineContext;
import org.springframework.statemachine.support.DefaultExtendedState;
import org.springframework.statemachine.support.DefaultStateMachineContext;
import org.springframework.statemachine.support.ObservableMap;

public final class StateMachineContextSerializer {
   public byte[] toByteArray(@NonNull StateMachineContext<FlowState, StateMachineFlowEvent> context) {
      if (context == null) {
         throw new NullPointerException("context is marked non-null but is null");
      }

      Output output = new Output(new ByteArrayOutputStream());

      byte[] var3;
      try {
         createKryo().writeObject(output, context);
         output.flush();
         var3 = ((ByteArrayOutputStream)output.getOutputStream()).toByteArray();
      } catch (Throwable var6) {
         try {
            output.close();
         } catch (Throwable var5) {
            var6.addSuppressed(var5);
         }

         throw var6;
      }

      output.close();
      return var3;
   }

   public StateMachineContext<FlowState, StateMachineFlowEvent> toStateMachineContext(byte @NonNull [] data) {
      if (data == null) {
         throw new NullPointerException("data is marked non-null but is null");
      }

      ByteArrayInputStream in = new ByteArrayInputStream(data);
      Input input = new Input(in);

      StateMachineContext var4;
      try {
         var4 = (StateMachineContext)createKryo().readObject(input, DefaultStateMachineContext.class);
      } catch (Throwable var7) {
         try {
            input.close();
         } catch (Throwable var6) {
            var7.addSuppressed(var6);
         }

         throw var7;
      }

      input.close();
      return var4;
   }

   private static Kryo createKryo() {
      Kryo kryo = new Kryo();
      kryo.addDefaultSerializer(StateMachineContext.class, new org.springframework.statemachine.kryo.StateMachineContextSerializer());
      kryo.setRegistrationRequired(true);
      Stream.of(ArrayList.class, DefaultExtendedState.class, DefaultStateMachineContext.class, FlowStateWithStep.class, HashMap.class, ObservableMap.class)
         .forEach(kryo::register);
      return kryo;
   }
}
