'''
Copyright 2019 Google LLC

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

    https://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.
'''


import os
import platform
import queue
import select
import socket
import sys
import threading


TYPE_KEYBOARD_INPUT = 0
TYPE_TERMINAL_OUTPUT = 1
TYPE_REMOTE_CLOSED = 2
TYPE_SOCKET_TIMEOUT = 3


class ConnectionClosedError(Exception):
    def __init__(self, exit_code=None):
        self.exit_code = exit_code


class SocketTimeoutError(Exception):
    pass


def GetTtyWindowSize(fd):
    import fcntl
    import struct
    import termios
    tty_size = fcntl.ioctl(fd, termios.TIOCGWINSZ, '....')
    return struct.unpack('hh', tty_size)


class PosixConsole:
    def __init__(self, channel, inputfile):
        self.channel = channel
        self.inputfile = inputfile
        self.has_tty = False

    def _updateWindowSize(self, signum, stackFrame):
        if self.has_tty:
            (rows, columns) = GetTtyWindowSize(self.inputfile)
            self.channel.resize_pty(columns, rows, 0, 0)

    def run(self):
        import termios
        import tty
        import signal

        from termios import ISTRIP, INLCR, IGNCR, ICRNL, IXON, IXANY, IXOFF
        from termios import ISIG, ICANON, ECHO, ECHOE, ECHOK, ECHONL
        from termios import OPOST, VMIN, VTIME
        from termios import TCSADRAIN

        has_tty = False
        old_tty_attrs = None
        escape_level = 0

        try:
            old_tty_attrs = termios.tcgetattr(self.inputfile)

            (iflag, oflag, cflag, lflag, ispeed, ospeed, cc) = old_tty_attrs
            iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF)
            lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL)
            oflag &= ~OPOST
            cc[VMIN] = 1
            cc[VTIME] = 0

            newattrs = [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
            termios.tcsetattr(self.inputfile, TCSADRAIN, newattrs)

            signal.signal(signal.SIGWINCH, self._updateWindowSize)

            self.has_tty = True

        except termios.error as e:
            self.has_tty = False

        try:
            self.channel.settimeout(0)

            while True:
                read, write, exception = select.select([self.channel,
                                                        self.inputfile],
                                                       [], [])

                # data from device to host
                if self.channel in read:
                    try:
                        data = self.channel.recv(256)
                        if not data:
                            exit_code = None
                            if self.channel.exit_status_ready():
                                exit_code = self.channel.recv_exit_status()
                            raise ConnectionClosedError(exit_code=exit_code)
                        sys.stdout.write(data.decode("utf-8", errors="ignore"))
                        sys.stdout.flush()
                    except socket.timeout as e:
                        raise SocketTimeoutError(e)

                # data from host to device
                if self.inputfile in read:
                    fd = self.inputfile.fileno()
                    data = os.read(fd, 1)

                    if escape_level == 0 and data == b'\r':
                        escape_level += 1
                    elif escape_level == 1 and data == b'~':
                        escape_level += 1
                        continue
                    elif escape_level == 2 and data == b'.':
                        raise ConnectionClosedError(exit_code=0)
                    else:
                        escape_level = 0

                    if not data:
                        exit_code = None
                        if self.channel.exit_status_ready():
                            exit_code = self.channel.recv_exit_status()
                        raise ConnectionClosedError(exit_code=exit_code)

                    self.channel.send(data)
        finally:
            if self.has_tty:
                termios.tcsetattr(self.inputfile, TCSADRAIN, old_tty_attrs)


class KeyboardInputThread(threading.Thread):
    def __init__(self, queue):
        super(KeyboardInputThread, self).__init__()
        self.daemon = True
        self.queue = queue

    def run(self):
        while True:
            ch = sys.stdin.read(1)
            self.queue.put((KEYBOARD_INPUT_DATA, ch))


class TerminalOutputThread(threading.Thread):
    def __init__(self, queue, channel):
        super(TerminalOutputThread, self).__init__()
        self.daemon = True
        self.queue = queue
        self.channel = channel

    def run(self):
        while True:
            try:
                data = self.channel.recv(256)
                if not data:
                    exit_code = None
                    if self.channel.exit_status_ready():
                        exit_code = self.channel.recv_exit_status()
                    self.queue.put((TYPE_REMOTE_CLOSED, exit_code))
                    break
                data = data.decode("utf-8", errors="ignore")
                self.queue.put((TYPE_TERMINAL_OUTPUT, data))
            except socket.timeout:
                self.queue.put((TYPE_SOCKET_TIMEOUT, None))
                break

        exit_status = self.channel.recv_exit_status()
        self.queue.put((TYPE_EXIT_CODE, exit_status))


class WindowsConsole:
    def __init__(self, channel, inputfile):
        self.channel = channel
        self.dataQueue = queue.Queue()
        self.inputThread = KeyboardInputThread(self.dataQueue)
        self.outputThread = TerminalOutputThread(self.dataQueue, self.channel)

    def run(self):
        self.inputThread.start()
        self.outputThread.start()

        escape_level = 0

        while True:
            dataType, data = self.queue.get()

            if dataType == TYPE_KEYBOARD_INPUT:
                if escape_level == 0 and data == b'\r':
                    escape_level += 1
                elif escape_level == 1 and data == b'~':
                    escape_level += 1
                    continue
                elif escape_level == 2 and data == b'.':
                    raise ConnectionClosedError(exit_code=0)
                else:
                    escape_level = 0

                channel.send(data)
            if dataType == TYPE_TERMINAL_OUTPUT:
                sys.stdout.write(data)
                sys.stdout.flush()
            if dataType == TYPE_REMOTE_CLOSED:
                raise ConnectionClosedError(exit_code=data)
            if dataType == TYPE_SOCKET_TIMEOUT:
                raise SocketTimeoutError()


class Console:
    def __init__(self, channel, inputfile):
        if os.name == 'nt':
            self._console = WindowsConsole(channel, inputfile)
        else:
            self._console = PosixConsole(channel, inputfile)

    def run(self):
        return self._console.run()
