#!/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)

      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(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:]))
