/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.chromium.latency.walt;

import android.content.Context;
import android.content.res.Resources;
import android.hardware.usb.UsbDevice;
import android.os.Handler;
import android.util.Log;

import java.io.IOException;

/**
 * A singleton used as an interface for the physical WALT device.
 */
public class WaltDevice implements WaltConnection.ConnectionStateListener {

    private static final int DEFAULT_DRIFT_LIMIT_US = 1500;
    private static final String TAG = "WaltDevice";
    public static final String PROTOCOL_VERSION = "5";

    // Teensy side commands. Each command is a single char
    // Based on #defines section in walt.ino
    static final char CMD_PING_DELAYED     = 'D'; // Ping with a delay
    static final char CMD_RESET            = 'F'; // Reset all vars
    static final char CMD_SYNC_SEND        = 'I'; // Send some digits for clock sync
    static final char CMD_PING             = 'P'; // Ping with a single byte
    static final char CMD_VERSION          = 'V'; // Determine WALT's firmware version
    static final char CMD_SYNC_READOUT     = 'R'; // Read out sync times
    static final char CMD_GSHOCK           = 'G'; // Send last shock time and watch for another shock.
    static final char CMD_TIME_NOW         = 'T'; // Current time
    static final char CMD_SYNC_ZERO        = 'Z'; // Initial zero
    static final char CMD_AUTO_SCREEN_ON   = 'C'; // Send a message on screen color change
    static final char CMD_AUTO_SCREEN_OFF  = 'c';
    static final char CMD_SEND_LAST_SCREEN = 'E'; // Send info about last screen color change
    static final char CMD_BRIGHTNESS_CURVE = 'U'; // Probe screen for brightness vs time curve
    static final char CMD_AUTO_LASER_ON    = 'L'; // Send messages on state change of the laser
    static final char CMD_AUTO_LASER_OFF   = 'l';
    static final char CMD_SEND_LAST_LASER  = 'J';
    static final char CMD_AUDIO            = 'A'; // Start watching for signal on audio out line
    static final char CMD_BEEP             = 'B'; // Generate a tone into the mic and send timestamp
    static final char CMD_BEEP_STOP        = 'S'; // Stop generating tone
    static final char CMD_MIDI             = 'M'; // Start listening for a MIDI message
    static final char CMD_NOTE             = 'N'; // Generate a MIDI NoteOn message

    private static final int BYTE_BUFFER_SIZE = 1024 * 4;
    private byte[] buffer = new byte[BYTE_BUFFER_SIZE];

    private Context context;
    protected SimpleLogger logger;
    private WaltConnection connection;
    public RemoteClockInfo clock;
    private WaltConnection.ConnectionStateListener connectionStateListener;

    private static final Object LOCK = new Object();
    private static WaltDevice instance;

    public static WaltDevice getInstance(Context context) {
        synchronized (LOCK) {
            if (instance == null) {
                instance = new WaltDevice(context.getApplicationContext());
            }
            return instance;
        }
    }

    private WaltDevice(Context context) {
        this.context = context;
        triggerListener = new TriggerListener();
        logger = SimpleLogger.getInstance(context);
    }

    public void onConnect() {
        try {
            // TODO: restore
            softReset();
            checkVersion();
            syncClock();
        } catch (IOException e) {
            logger.log("Unable to communicate with WALT: " + e.getMessage());
        }

        if (connectionStateListener != null) {
            connectionStateListener.onConnect();
        }
    }

    // Called when disconnecting from WALT
    // TODO: restore this, not called from anywhere
    public void onDisconnect() {
        if (!isListenerStopped()) {
            stopListener();
        }

        if (connectionStateListener != null) {
            connectionStateListener.onDisconnect();
        }
    }

    public void connect() {
        if (WaltTcpConnection.probe()) {
            logger.log("Using TCP bridge for ChromeOS");
            connection = WaltTcpConnection.getInstance(context);
        } else {
            // USB connection
            logger.log("No TCP bridge detected, using direct USB connection");
            connection = WaltUsbConnection.getInstance(context);
        }
        connection.setConnectionStateListener(this);
        connection.connect();
    }

    public void connect(UsbDevice usbDevice) {
        // This happens when apps starts as a result of plugging WALT into USB. In this case we
        // receive an intent with a usbDevice
        WaltUsbConnection usbConnection = WaltUsbConnection.getInstance(context);
        connection = usbConnection;
        connection.setConnectionStateListener(this);
        usbConnection.connect(usbDevice);
    }

    public boolean isConnected() {
        return connection.isConnected();
    }


    public String readOne() throws IOException {
        if (!isListenerStopped()) {
            throw new IOException("Can't do blocking read while listener is running");
        }

        byte[] buff = new byte[64];
        int ret = connection.blockingRead(buff);

        if (ret < 0) {
            throw new IOException("Timed out reading from WALT");
        }
        String s = new String(buff, 0, ret);
        Log.i(TAG, "readOne() received data: " + s);
        return s;
    }


    private String sendReceive(char c) throws IOException {
        connection.sendByte(c);
        return readOne();
    }

    public void sendAndFlush(char c) {

        try {
            connection.sendByte(c);
            while(connection.blockingRead(buffer) > 0) {
                // flushing all incoming data
            }
        } catch (Exception e) {
            logger.log("Exception in sendAndFlush: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public void softReset() {
        sendAndFlush(CMD_RESET);
    }

    String command(char cmd, char ack) throws IOException {
        if (!isListenerStopped()) {
            connection.sendByte(cmd); // TODO: check response even if the listener is running
            return "";
        }
        String response = sendReceive(cmd);
        if (!response.startsWith(String.valueOf(ack))) {
            throw new IOException("Unexpected response from WALT. Expected \"" + ack
                    + "\", got \"" + response + "\"");
        }
        return response.substring(1).trim();
    }

    String command(char cmd) throws IOException {
        return command(cmd, flipCase(cmd));
    }

    private char flipCase(char c) {
        if (Character.isUpperCase(c)) {
            return Character.toLowerCase(c);
        } else if (Character.isLowerCase(c)) {
            return Character.toUpperCase(c);
        } else {
            return c;
        }
    }

    public void checkVersion() throws IOException {
        if (!isConnected()) throw new IOException("Not connected to WALT");
        if (!isListenerStopped()) throw new IOException("Listener is running");

        String s = command(CMD_VERSION);
        if (!PROTOCOL_VERSION.equals(s)) {
            Resources res = context.getResources();
            throw new IOException(String.format(res.getString(R.string.protocol_version_mismatch),
                    s, PROTOCOL_VERSION));
        }
    }

    public void syncClock() throws IOException {
        clock = connection.syncClock();
    }

    // Simple way of syncing clocks. Used for diagnostics. Accuracy of several ms.
    public void simpleSyncClock() throws IOException {
        byte[] buffer = new byte[1024];
        clock = new RemoteClockInfo();
        clock.baseTime = RemoteClockInfo.microTime();
        String reply = sendReceive(CMD_SYNC_ZERO);
        logger.log("Simple sync reply: " + reply);
        clock.maxLag = (int) clock.micros();
        logger.log("Synced clocks, the simple way:\n" + clock);
    }

    public void checkDrift() {
        if (! isConnected()) {
            logger.log("ERROR: Not connected, aborting checkDrift()");
            return;
        }
        connection.updateLag();
        int drift = Math.abs(clock.getMeanLag());
        String msg = String.format("Remote clock delayed between %d and %d us",
                clock.minLag, clock.maxLag);
        // TODO: Convert the limit to user editable preference
        if (drift > DEFAULT_DRIFT_LIMIT_US) {
            msg = "WARNING: High clock drift. " + msg;
        }
        logger.log(msg);
    }

    public long readLastShockTime_mock() {
        return clock.micros() - 15000;
    }

    public long readLastShockTime() {
        String s;
        try {
            s = sendReceive(CMD_GSHOCK);
        } catch (IOException e) {
            logger.log("Error sending GSHOCK command: " + e.getMessage());
            return -1;
        }
        Log.i(TAG, "Received S reply: " + s);
        long t = 0;
        try {
            t = Integer.parseInt(s.trim());
        } catch (NumberFormatException e) {
            logger.log("Bad reply for shock time: " + e.getMessage());
        }

        return t;
    }

    static class TriggerMessage {
        public char tag;
        public long t;
        public int value;
        public int count;
        // TODO: verify the format of the message while parsing it
        TriggerMessage(String s) {
            String[] parts = s.trim().split("\\s+");
            tag = parts[0].charAt(0);
            t = Integer.parseInt(parts[1]);
            value = Integer.parseInt(parts[2]);
            count = Integer.parseInt(parts[3]);
        }

        static boolean isTriggerString(String s) {
            return s.trim().matches("G\\s+[A-Z]\\s+\\d+\\s+\\d+.*");
        }
    }

    TriggerMessage readTriggerMessage(char cmd) throws IOException {
        String response = command(cmd, 'G');
        return new TriggerMessage(response);
    }


    /***********************************************************************************************
     Trigger Listener
     A thread that constantly polls the interface for incoming triggers and passes them to the handler

     */

    private TriggerListener triggerListener;
    private Thread triggerListenerThread;

    abstract static class TriggerHandler {
        private Handler handler;

        TriggerHandler() {
            handler = new Handler();
        }

        private void go(final String s) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    onReceiveRaw(s);
                }
            });
        }

        void onReceiveRaw(String s) {
            if (TriggerMessage.isTriggerString(s)) {
                TriggerMessage tmsg = new TriggerMessage(s.substring(1).trim());
                onReceive(tmsg);
            } else {
                Log.i(TAG, "Malformed trigger data: " + s);
            }
        }

        abstract void onReceive(TriggerMessage tmsg);
    }

    private TriggerHandler triggerHandler;

    void setTriggerHandler(TriggerHandler triggerHandler) {
        this.triggerHandler = triggerHandler;
    }

    void clearTriggerHandler() {
        triggerHandler = null;
    }

    private class TriggerListener implements Runnable {
        static final int BUFF_SIZE = 1024 * 4;
        public Utils.ListenerState state = Utils.ListenerState.STOPPED;
        private byte[] buffer = new byte[BUFF_SIZE];

        @Override
        public void run() {
            state = Utils.ListenerState.RUNNING;
            while(isRunning()) {
                int ret = connection.blockingRead(buffer);
                if (ret > 0 && triggerHandler != null) {
                    String s = new String(buffer, 0, ret);
                    Log.i(TAG, "Listener received data: " + s);
                    if (s.length() > 0) {
                        triggerHandler.go(s);
                    }
                }
            }
            state = Utils.ListenerState.STOPPED;
        }

        public synchronized boolean isRunning() {
            return state == Utils.ListenerState.RUNNING;
        }

        public synchronized boolean isStopped() {
            return state == Utils.ListenerState.STOPPED;
        }

        public synchronized void stop() {
            state = Utils.ListenerState.STOPPING;
        }
    }

    public boolean isListenerStopped() {
        return triggerListener.isStopped();
    }

    public void startListener() throws IOException {
        if (!isConnected()) {
            throw new IOException("Not connected to WALT");
        }
        triggerListenerThread = new Thread(triggerListener);
        logger.log("Starting Listener");
        triggerListener.state = Utils.ListenerState.STARTING;
        triggerListenerThread.start();
    }

    public void stopListener() {
        logger.log("Stopping Listener");
        triggerListener.stop();
        try {
            triggerListenerThread.join();
        } catch (Exception e) {
            logger.log("Error while stopping Listener: " + e.getMessage());
        }
        logger.log("Listener stopped");
    }

    public void setConnectionStateListener(WaltConnection.ConnectionStateListener connectionStateListener) {
        this.connectionStateListener = connectionStateListener;
        if (isConnected()) {
            this.connectionStateListener.onConnect();
        }
    }

}
