package com.eactive.testmaster.config;

import static javax.script.ScriptContext.GLOBAL_SCOPE;

import com.hazelcast.collection.IQueue;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.scheduledexecutor.IScheduledExecutorService;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.SimpleBindings;
import org.apache.commons.lang3.function.TriFunction;
import org.springframework.stereotype.Service;

@Service
public class HazelcastJSBridge {

    private final HazelcastInstance hazelcastInstance;
    private final IScheduledExecutorService scheduledExecutor;


    public HazelcastJSBridge(HazelcastInstance hazelcastInstance) {
        this.hazelcastInstance = hazelcastInstance;
        this.scheduledExecutor = hazelcastInstance.getScheduledExecutorService("delayed-queue-executor");

    }

    /**
     * Creates bindings for Hazelcast operations that can be used in JavaScript
     */
    public Bindings createHazelcastBindings() {
        Bindings bindings = new SimpleBindings();

        bindings.put("tmOfferToQueue", (java.util.function.BiFunction<String, Object, Boolean>)
            (queueName, item) -> {
                IQueue<Object> queue = hazelcastInstance.getQueue(queueName);
                return queue.offer(item);
            });

        bindings.put("tmPollFromQueue", (java.util.function.Function<String, Object>)
            queueName -> {
                IQueue<Object> queue = hazelcastInstance.getQueue(queueName);
                return queue.poll();
            });

        bindings.put("tmScheduleToQueue", (TriFunction<String, Object, Integer, Boolean>)
            (queueName, item, delaySeconds) -> {
                try {
                    scheduledExecutor.schedule(
                        () -> {
                            IQueue<Object> queue = hazelcastInstance.getQueue(queueName);
                            queue.offer(item);
                        },
                        delaySeconds,
                        TimeUnit.SECONDS
                    );
                    return true;
                } catch (Exception e) {
                    return false;
                }
            });

        // Utility operations
        bindings.put("tmGetDistributedObjects",
            (java.util.function.Supplier<Collection<?>>)
                () -> hazelcastInstance.getDistributedObjects());

        return bindings;
    }

    /**
     * Enhances the JavaScript engine with Hazelcast capabilities
     */
    public void enhanceEngine(ScriptEngine engine) {
        engine.setBindings(createHazelcastBindings(), GLOBAL_SCOPE);
    }
}
