package net.yak.kiwi;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

public class Nando {
    public static void main(String[] args) {
        System.out.println("Hello World");
        for (String a : args) {
            System.out.println("<" + a + ">");
        }

        new Nando().Run();
    }

    public void Run() {
        long now = System.currentTimeMillis() / 1000;
        try {
            URI url = new URI("ws://sybil.yak.net:8073/no_wf/" + now + "/SND");  // SEND
            System.err.println("Nando URL: " + url);
            MyWebSocketClient cl = new MyWebSocketClient(url);
            cl.connectBlocking();
            Thread.sleep(1000);
            cl.send("SET auth t=kiwi p=xyzzy");
            cl.send("SET AR OK in=12000 out=44100");
            cl.send("SET squelch=0 max=0");
            cl.send("SET lms_autonotch=0");
            cl.send("SET genattn=0");
            cl.send("SET gen=0 mix=-1");
            cl.send("SET ident_user=__Nando__");
            cl.send("SET mod=usb low_cut=300 high_cut=2700 freq=5000.000");
            cl.send("SET agc=1 hang=0 thresh=-100 slope=6 decay=1000 manGain=50");
            cl.send("SET compression=0");
            cl.send("SET OVERRIDE inactivity_timeout=0");

            Thread.sleep(5000);

            for (int i = 0; i < 10; i++ ) {
                cl.send("SET keepalive");
                Thread.sleep(1000);
            }
            cl.closeConnection(666, "closeConnection");

        } catch (java.lang.Exception ex) {
            System.err.println("Nando stops on exception: " + ex);
        }
    }


    class MyWebSocketClient extends WebSocketClient {
        Logger log = LoggerFactory.getLogger(MyWebSocketClient.class);

        private Map<String,String> serverValues = new HashMap<>();

        public MyWebSocketClient(URI url) {
            super(url);
        }

        @Override
        public void onOpen(ServerHandshake handshakedata) {
            System.err.println("WebSocketClient onOpen: status=" + handshakedata.getHttpStatus());
            System.err.println("WebSocketClient onOpen: status_message=" + handshakedata.getHttpStatusMessage());
        }

        @Override
        public void onMessage(String message) {  // TEXT message
            System.err.println("WebSocketClient onMessage TEXT: " + message);
            throw new RuntimeException("unexpected text message");
        }

        private void parseAndSaveServerValues(String s) {
            String[] items = s.split(" ");
            for (String e : items) {
                System.err.println("KV: " + e);
                if (e.contains("=")) {
                    String[] kv = e.split("=");
                    if (kv.length >= 2) {
                        serverValues.put(kv[0], kv[1]);
                    }
                } else {
                    serverValues.put(e, "<default>");
                }
            }
        }

        @Override
        public void onMessage(ByteBuffer buf) {  // BINARY message
            int n = buf.remaining();
            byte[] bb = new byte[n];
            buf.get(bb);
            if (bb.length < 5) {
                throw new RuntimeException("short message: " + new String(bb));
            }
            String label = new String(bb, 0, 3);
            if (label.equals("MSG")) {
                String argument = new String(bb, 4, bb.length-4);
                parseAndSaveServerValues(argument);
            } else if (label.equals("SND")) {
                log.info("Got SND: totlen=" + bb.length);
                //log.info("RAW=" + log.curly(new String(bb, 0, 20)));
                doAudio(bb);
            } else {
                log.error("Unknown label: <" + log.curly(label) + "> totlen=" + bb.length);
            }
        }

        private void doAudio(byte[] bb) {
            // First 10 bytes are header:
            //   0..2 : 'SND'
            //   3: flag: (unsigned byte)
            //   4..7: sequence: little-endian signed int32
            //   8..9: smeter: big-endian unsigned uint16
            // Rest are big-endian signed int16 audio samples.
            for (int i = 10; i < bb.length; i += 2) {
                // swap bytes so they are little-endian for Linux amd64
                byte t = bb[i];
                bb[i] = bb[i+1];
                bb[i+1] = t;
            }
            System.out.write(bb, 10, bb.length-10);
        }

        @Override
        public void onClose(int code, String reason, boolean remote) {
            System.err.println("WebSocketClient onClose: " + reason);
        }

        @Override
        public void onError(Exception ex) {
            System.err.println("WebSocketClient onError: " + ex);
        }
    }
}
