#!/usr/bin/env python
# Copyright (C) 2019 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.

from __future__ import print_function
import sys
import os
import time
import argparse
import socket
import subprocess
import threading

try:
  import socketserver
  from http.server import SimpleHTTPRequestHandler
except ImportError:
  import SocketServer as socketserver
  import SimpleHTTPServer
  SimpleHTTPRequestHandler = SimpleHTTPServer.SimpleHTTPRequestHandler


class TCPServer(socketserver.TCPServer):

  def server_bind(self):
    self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    self.socket.bind(self.server_address)


class Server(object):

  def __init__(self, port, directory, rebuilder):
    self.port = port
    self.directory = directory
    self.rebuilder = rebuilder
    self.lock = threading.Lock()

  def serve(self):
    this = self

    class Handler(SimpleHTTPRequestHandler):

      def __init__(self, *args, **kwargs):
        SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)
        self.extensions_map['.wasm'] = 'application/wasm'

      def translate_path(self, path):
        path = SimpleHTTPRequestHandler.translate_path(self, path)
        relpath = os.path.relpath(path, os.getcwd())
        fullpath = os.path.join(this.directory, relpath)
        return fullpath

      def do_GET(self):
        try:
          with this.lock:
            this.rebuilder.rebuild_if_needed()
        except RebuildFailed as e:
          self.send_response(200)
          self.send_header("Content-type", "text/html")
          self.end_headers()
          self.wfile.write("<pre>")
          self.wfile.write(e.stdout_and_stderr)
          return
        return SimpleHTTPRequestHandler.do_GET(self)

    print('Starting server at http://localhost:{}'.format(self.port))
    httpd = TCPServer(('', self.port), Handler)
    try:
      httpd.serve_forever()
    except KeyboardInterrupt:
      httpd.shutdown()
    httpd.server_close()


class RebuildFailed(Exception):

  def __init__(self, stdout_and_stderr):
    self.stdout_and_stderr = stdout_and_stderr


class Rebuilder(object):

  def __init__(self, command, ignored_paths):
    self.command = command
    self.ignored_paths = ignored_paths
    self.last_disk_state = None
    self.abs_ignored_paths = [os.path.abspath(p) for p in self.ignored_paths]

  def rebuild_if_needed(self):
    if self.last_disk_state == self.last_modified_time():
      return
    stdout_and_stderr, success = self.rebuild()
    if not success:
      message = b"Failed to build! Command output:\n\n" + stdout_and_stderr
      raise RebuildFailed(message)
    self.last_disk_state = self.last_modified_time()

  def last_modified_time(self):
    start_time = time.time()
    max_mtime = 0
    for dirpath, dirnames, filenames in os.walk(
        os.path.abspath('.'), topdown=True):
      dirnames[:] = [
          n for n in dirnames
          if not self.should_ignore_path(os.path.join(dirpath, n))
      ]
      for filename in filenames:
        path = os.path.join(dirpath, filename)
        if self.should_ignore_path(path):
          continue
        mtime = os.stat(path).st_mtime
        max_mtime = max(max_mtime, mtime)
    print(' scanned in {:.03f}s'.format(time.time() - start_time).rjust(
        80, '='))
    return max_mtime

  def should_ignore_path(self, path):
    return path in self.abs_ignored_paths

  def rebuild(self):
    print('Running command: {}'.format(self.command))
    print(' begin build'.rjust(80, '='))
    start_time = time.time()
    status = 0
    try:
      stdout_and_stderr = subprocess.check_output(
          self.command, shell=True, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
      status = e.returncode
      stdout_and_stderr = e.output
    print(stdout_and_stderr.decode('utf8'))
    print(' built in {:.03f}s'.format(time.time() - start_time).rjust(80, '='))
    return stdout_and_stderr, status == 0


def main(argv):
  parser = argparse.ArgumentParser(description='HTTP server for UI development')
  parser.add_argument(
      '-p',
      '--port',
      help='port number (default: 3000)',
      type=int,
      default=3000)
  parser.add_argument(
      '-i', '--ignore', default=[], action='append', help='Ignore this path')
  parser.add_argument(
      '-s',
      '--serve',
      default=os.getcwd(),
      help='Serve this directory (default: current directory)')
  parser.add_argument('command', default='', nargs='?', help='Command to run')

  args = parser.parse_args(argv)

  rebuilder = Rebuilder(args.command, args.ignore)
  server = Server(args.port, args.serve, rebuilder)
  server.serve()
  return 0


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