#!/usr/bin/env python
#
# Copyright 2018 The Cobalt Authors. All Rights Reserved.
#
# 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.

"""Example script for getting the Net log."""

from __future__ import print_function

import argparse
import pprint
import select
import socket
import sys
import time
import threading

class NetLog:
  """
  Uses a non-blocking socket to establish a connection with a
  NetLog and then will allow the log to be fetched.
  """
  def __init__(self, host, port):
    self.host = host
    self.port = port
    self.server_socket = None

  def FetchLog(self):
    if not self.server_socket:
      self.server_socket = self._TryCreateSocketConnection()
      if not self.server_socket:
        return None
    try:
      log = self._TryRead()
      if log is None:
        self.server_socket = None
      else:
        return log
    except socket.error as (err_no, err_str):
      print(__file__ + ": Socket error while reading log:" \
            + str(err_no) + " - " + str(err_str))
      self.server_socket = None
      return None

  # Private members
  def _TryRead(self):
    try:
      ready_list, _, _ = select.select([self.server_socket], [], [])
      if not ready_list:
        return ''
      result = self.server_socket.recv(1024)
      # An empty string is a flag that the connection has closed.
      if len(result) == 0:
        return None
      return result
    except socket.error as (err_no, err_str):
      if err_no == 10035:  # Data not ready yet.
        return ''
      else:
        raise

  def _TryCreateSocketConnection(self):
    try:
      print("Waiting for connection to " + str(self.host) + ':' + str(self.port))

      server_socket = socket.create_connection((self.host, self.port), timeout = 1)
      server_socket.setblocking(0)
      return server_socket
    except socket.timeout as err:
      return None
    except socket.error as err:
      print("Error while trying to create socket: " + str(err))
      return None


class NetLogThread(threading.Thread):
  """Threaded version of NetLog"""
  def __init__(self, host, port):
    super(NetLogThread, self).__init__()
    self.web_log = NetLog(host, port)
    self.alive = True
    self.log_mutex = threading.Lock()
    self.log = []
    self.start()

  def join(self):
    self.alive = False
    return super(NetLogThread, self).join()

  def GetLog(self):
    with self.log_mutex:
      log_copy = self.log
      self.log = []
      return ''.join(log_copy)

  def run(self):
    while self.alive:
      new_log = self.web_log.FetchLog()
      if new_log:
        with self.log_mutex:
          self.log.extend(new_log)

def TestNetLog(host, port):
  print("Started...")
  web_log = NetLog(host, port)

  while True:
    log = web_log.FetchLog()
    if log:
      print(log, end='')
    time.sleep(.1)


def main(argv):
  parser = argparse.ArgumentParser(description = 'Connects to the weblog.')
  parser.add_argument('--host', type=str, required = False,
                      default = 'localhost',
                      help = "Example localhost or 1.2.3.4")
  parser.add_argument('--port', type=int, required = False, default = '49353')
  args = parser.parse_args(argv)

  thread = NetLogThread(args.host, args.port)

  try:
    while True:
      print(thread.GetLog(), end='')
      time.sleep(.1)
  except KeyboardInterrupt as ki:
    print("\nUser canceled.")
    pass

  print("Waiting to join...")
  thread.join()
  return 0

if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
