package ru.kirillius.cooler.controller.API;

import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

public final class DummyMessageSystem extends MessageSystem {
    private final Worker worker;
    private final Map<DataType, Byte> values = new ConcurrentHashMap<>();

    public DummyMessageSystem() throws MessageException {
        super();
        addDefaults();
        worker = new Worker();
        worker.start();
    }

    private void addDefaults() {
        values.put(DataType.TEMP, (byte) 0x20);
        values.put(DataType.LEVEL, (byte) 128);
        values.put(DataType.MIN_LEVEL, (byte) 10);
        values.put(DataType.MAX_LEVEL, (byte) 255);
        values.put(DataType.MAX_TEMP, (byte) 40);
        values.put(DataType.START_TEMP, (byte) 25);
        values.put(DataType.STOP_TEMP, (byte) 20);
    }

    @Override
    public void sendMessage(Message message) {
        switch (message.getActionType()) {
            case SAVE:
            case PING:
            case REBOOT:
                worker.add(message);
                break;
            case READ:
                if (values.containsKey(message.getDataType())) {
                    message.setValue(values.get(message.getDataType()));
                    worker.add(message);
                }
                break;
            case WRITE:
                if (values.containsKey(message.getDataType())) {
                    values.put(message.getDataType(), message.getValue());
                    worker.add(message);
                }
                break;
        }

    }


    @Override
    protected void OnClose() {
        worker.interrupt();
    }


    private class Worker extends Thread {
        private final Queue<Message> messageQueue = new ConcurrentLinkedQueue<>();

        @SuppressWarnings("BusyWait")
        @Override
        public void run() {
            int temp = 20;
            int level = 0;
            int ping = 0;

            while (!interrupted()) {
                if (ping++ % 5 == 0) {
                    Message m = new Message(ActionType.PING, DataType.NONE, (byte) 123);
                    m.validate();
                    OnMessageReceived(m);
                }
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    return;
                }
                if (!messageQueue.isEmpty()) {
                    OnMessageReceived(messageQueue.poll());
                }
                temp++;
                level++;
                if (temp >= 100) temp = 15;
                if (level >= 256) level = 0;

                values.put(DataType.LEVEL, (byte) (level & 0xFF));
                values.put(DataType.TEMP, (byte) (temp & 0xFF));

            }
        }

        public void add(Message m) {
            m.validate();
            messageQueue.add(m);
        }
    }
}
