#!/usr/bin/python
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import datetime
import fnmatch
import logging
import os
import os.path
import queue as Queue
import sublime
import sublime_plugin
import subprocess
import sys
import tempfile
import threading
import time

# Path to the version of ninja checked in into Chrome.
rel_path_to_ninja = os.path.join('third_party', 'depot_tools', 'ninja')


class PrintOutputCommand(sublime_plugin.TextCommand):
    def run(self, edit, **args):
        self.view.set_read_only(False)
        self.view.insert(edit, self.view.size(), args['text'])
        self.view.show(self.view.size())
        self.view.set_read_only(True)


class CompileCurrentFile(sublime_plugin.TextCommand):
  # static thread so that we don't try to run more than once at a time.
  thread = None
  lock = threading.Lock()

  def __init__(self, args):
    super(CompileCurrentFile, self).__init__(args)
    self.thread_id = threading.current_thread().ident
    self.text_to_draw = ""
    self.interrupted = False

  def description(self):
    return ("Compiles the file in the current view using Ninja, so all that "
            "this file and it's project depends on will be built first\n"
            "Note that this command is a toggle so invoking it while it runs "
            "will interrupt it.")

  def draw_panel_text(self):
    """Draw in the output.exec panel the text accumulated in self.text_to_draw.

    This must be called from the main UI thread (e.g., using set_timeout).
    """
    assert self.thread_id == threading.current_thread().ident
    logging.debug("draw_panel_text called.")
    self.lock.acquire()
    text_to_draw = self.text_to_draw
    self.text_to_draw = ""
    self.lock.release()

    if len(text_to_draw):
      self.output_panel.run_command('print_output', {'text': text_to_draw})
      self.view.window().run_command("show_panel", {"panel": "output.exec"})
      logging.debug("Added text:\n%s.", text_to_draw)

  def update_panel_text(self, text_to_draw):
    self.lock.acquire()
    self.text_to_draw += text_to_draw
    self.lock.release()
    sublime.set_timeout(self.draw_panel_text, 0)

  def execute_command(self, command, cwd):
    """Execute the provided command and send ouput to panel.

    Because the implementation of subprocess can deadlock on windows, we use
    a Queue that we write to from another thread to avoid blocking on IO.

    Args:
      command: A list containing the command to execute and it's arguments.
    Returns:
      The exit code of the process running the command or,
       1 if we got interrupted.
      -1 if we couldn't start the process
      -2 if we couldn't poll the running process
    """
    logging.debug("Running command: %s", command)

    def EnqueueOutput(out, queue):
      """Read all the output from the given handle and insert it into the queue.

      Args:
        queue: The Queue object to write to.
      """
      while True:
        # This readline will block until there is either new input or the handle
        # is closed. Readline will only return None once the handle is close, so
        # even if the output is being produced slowly, this function won't exit
        # early.
        # The potential dealock here is acceptable because this isn't run on the
        # main thread.
        data = out.readline()
        if not data:
          break
        queue.put(data, block=True)
      out.close()

    try:
      os.chdir(cwd)
      proc = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True,
                              stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
    except OSError as e:
      logging.exception('Execution of %s raised exception: %s.', (command, e))
      return -1

    # Use a Queue to pass the text from the reading thread to this one.
    stdout_queue = Queue.Queue()
    stdout_thread = threading.Thread(target=EnqueueOutput,
                                     args=(proc.stdout, stdout_queue))
    stdout_thread.daemon = True  # Ensure this exits if the parent dies
    stdout_thread.start()

    # We use the self.interrupted flag to stop this thread.
    while not self.interrupted:
      try:
        exit_code = proc.poll()
      except OSError as e:
        logging.exception('Polling execution of %s raised exception: %s.',
                          command, e)
        return -2

      # Try to read output content from the queue
      current_content = ""
      for _ in range(2048):
        try:
          current_content += stdout_queue.get_nowait().decode('utf-8')
        except Queue.Empty:
          break
      self.update_panel_text(current_content)
      current_content = ""
      if exit_code is not None:
        while stdout_thread.isAlive() or not stdout_queue.empty():
          try:
            current_content += stdout_queue.get(
                               block=True, timeout=1).decode('utf-8')
          except Queue.Empty:
            # Queue could still potentially contain more input later.
            pass
        time_length = datetime.datetime.now() - self.start_time
        self.update_panel_text("%s\nDone!\n(%s seconds)" %
                               (current_content, time_length.seconds))
        return exit_code
      # We sleep a little to give the child process a chance to move forward
      # before we poll it again.
      time.sleep(0.1)

    # If we get here, it's because we were interrupted, kill the process.
    proc.terminate()
    return 1

  def run(self, edit, target_build):
    """The method called by Sublime Text to execute our command.

    Note that this command is a toggle, so if the thread is are already running,
    calling run will interrupt it.

    Args:
      edit: Sumblime Text specific edit brace.
      target_build: Release/Debug/Other... Used for the subfolder of out.
    """
    # There can only be one... If we are running, interrupt and return.
    if self.thread and self.thread.is_alive():
      self.interrupted = True
      self.thread.join(5.0)
      self.update_panel_text("\n\nInterrupted current command:\n%s\n" % command)
      self.thread = None
      return

    # It's nice to display how long it took to build.
    self.start_time = datetime.datetime.now()
    # Output our results in the same panel as a regular build.
    self.output_panel = self.view.window().get_output_panel("exec")
    self.output_panel.set_read_only(True)
    self.view.window().run_command("show_panel", {"panel": "output.exec"})
    # TODO(mad): Not sure if the project folder is always the first one... ???
    project_folder = self.view.window().folders()[0]
    self.update_panel_text("Compiling current file %s\n" %
                           self.view.file_name())
    # The file must be somewhere under the project folder...
    if (project_folder.lower() !=
        self.view.file_name()[:len(project_folder)].lower()):
      self.update_panel_text(
          "ERROR: File %s is not in current project folder %s\n" %
              (self.view.file_name(), project_folder))
    else:
      output_dir = os.path.join(project_folder, 'out', target_build)
      source_relative_path = os.path.relpath(self.view.file_name(),
                                             output_dir)
      # On Windows the caret character needs to be escaped as it's an escape
      # character.
      carets = '^'
      if sys.platform.startswith('win'):
        carets = '^^'
      command = [
          os.path.join(project_folder, rel_path_to_ninja), "-C",
          os.path.join(project_folder, 'out', target_build),
          source_relative_path + carets]
      self.update_panel_text(' '.join(command) + '\n')
      self.interrupted = False
      self.thread = threading.Thread(target=self.execute_command,
                                     kwargs={"command":command,
                                             "cwd": output_dir})
      self.thread.start()

    time_length = datetime.datetime.now() - self.start_time
    logging.debug("Took %s seconds on UI thread to startup",
                  time_length.seconds)
    self.view.window().focus_view(self.view)
