package com.tangleroad.rensa;

import com.tangleroad.rensa.procs.log;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeInputEvent;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.TimeUnit;

public class GlobalKeyConsumer implements NativeKeyListener {

    public static GlobalKeyConsumer instance;

    private Set<Integer> consume = new HashSet<>();

    public GlobalKeyConsumer() {
        instance = this;
        GlobalScreen.setEventDispatcher(new VoidDispatchService());
        GlobalScreen.addNativeKeyListener(this);
    }

    public void dontConsumeKeyCode(int keycode) {
        // holy naming conventions..
        consume.remove(keycode);
    }

    public void consumeKeyCode(int keycode) {
        consume.add(keycode);
    }

    private void consume(NativeKeyEvent e) {
        int code = e.getKeyCode();
        if (consume.contains(code)) {
            System.out.print("Attempting to consume " + code + "[" + NativeKeyEvent.getKeyText(code) + "] event...\t");
            reflectConsume(e);
        } else if (code == NativeKeyEvent.VC_ALT) {
            if (e.getKeyLocation() == 3) { // right alt
//                log.info("Attempting to consume right alt...\t");
//                reflectConsume(e);
            }
        }
    }

    public void reflectConsume(NativeKeyEvent e) {
        try {
            Field f = NativeInputEvent.class.getDeclaredField("reserved");
            f.setAccessible(true);
            f.setShort(e, (short) 0x01);

            System.out.print("[ OK ]\n");
        } catch (Exception ex) {
            System.out.print("[ !! ]\n");
            ex.printStackTrace();
        }
    }

    public void nativeKeyPressed(NativeKeyEvent e) {
        consume(e);
    }

    public void nativeKeyReleased(NativeKeyEvent e) {
//        consume(e);

    }

    public void nativeKeyTyped(NativeKeyEvent e) {
    }

    private class VoidDispatchService extends AbstractExecutorService {
        private boolean running = false;

        private VoidDispatchService() {
            running = true;
        }

        public void shutdown() {
            running = false;
        }

        public List<Runnable> shutdownNow() {
            running = false;
            return new ArrayList<Runnable>(0);
        }

        public boolean isShutdown() {
            return !running;
        }

        public boolean isTerminated() {
            return !running;
        }

        public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
            return true;
        }

        public void execute(Runnable r) {
            r.run();
        }
    }

}