#!/usr/bin/python
#
# Copyright 2010 Google Inc. All Rights Reserved.
#

import logging
import os
import re
import threading

from automation.common import job
from automation.common import logger
from automation.server.job_executer import JobExecuter


class IdProducerPolicy(object):
  """Produces series of unique integer IDs.

  Example:
      id_producer = IdProducerPolicy()
      id_a = id_producer.GetNextId()
      id_b = id_producer.GetNextId()
      assert id_a != id_b
  """

  def __init__(self):
    self._counter = 1

  def Initialize(self, home_prefix, home_pattern):
    """Find first available ID based on a directory listing.

    Args:
      home_prefix: A directory to be traversed.
      home_pattern: A regexp describing all files/directories that will be
        considered. The regexp must contain exactly one match group with name
        "id", which must match an integer number.

    Example:
      id_producer.Initialize(JOBDIR_PREFIX, 'job-(?P<id>\d+)')
    """
    harvested_ids = []

    if os.path.isdir(home_prefix):
      for filename in os.listdir(home_prefix):
        path = os.path.join(home_prefix, filename)

        if os.path.isdir(path):
          match = re.match(home_pattern, filename)

          if match:
            harvested_ids.append(int(match.group('id')))

    self._counter = max(harvested_ids or [0]) + 1

  def GetNextId(self):
    """Calculates another ID considered to be unique."""
    new_id = self._counter
    self._counter += 1
    return new_id


class JobManager(threading.Thread):
  def __init__(self, machine_manager):
    threading.Thread.__init__(self, name=self.__class__.__name__)
    self.all_jobs = []
    self.ready_jobs = []
    self.job_executer_mapping = {}

    self.machine_manager = machine_manager

    self._lock = threading.Lock()
    self._jobs_available = threading.Condition(self._lock)
    self._exit_request = False

    self.listeners = []
    self.listeners.append(self)

    self._id_producer = IdProducerPolicy()
    self._id_producer.Initialize(job.Job.WORKDIR_PREFIX, 'job-(?P<id>\d+)')

    self._logger = logging.getLogger(self.__class__.__name__)

  def StartJobManager(self):
    self._logger.info("Starting...")

    with self._lock:
      self.start()
      self._jobs_available.notifyAll()

  def StopJobManager(self):
    self._logger.info("Shutdown request received.")

    with self._lock:
      for job_ in self.all_jobs:
        self._KillJob(job_.id)

      # Signal to die
      self._exit_request = True
      self._jobs_available.notifyAll()

    # Wait for all job threads to finish
    for executer in self.job_executer_mapping.values():
      executer.join()

  def KillJob(self, job_id):
    """Kill a job by id.

    Does not block until the job is completed.
    """
    with self._lock:
      self._KillJob(job_id)

  def GetJob(self, job_id):
    for job_ in self.all_jobs:
      if job_.id == job_id:
        return job_
    return None

  def _KillJob(self, job_id):
    self._logger.info("Killing [Job: %d].", job_id)

    if job_id in self.job_executer_mapping:
      self.job_executer_mapping[job_id].Kill()
    for job_ in self.ready_jobs:
      if job_.id == job_id:
        self.ready_jobs.remove(job_)
        break

  def AddJob(self, job_):
    with self._lock:
      job_.id = self._id_producer.GetNextId()

      self.all_jobs.append(job_)
      # Only queue a job as ready if it has no dependencies
      if job_.is_ready:
        self.ready_jobs.append(job_)

      self._jobs_available.notifyAll()

    return job_.id

  def CleanUpJob(self, job_):
    with self._lock:
      if job_.id in self.job_executer_mapping:
        self.job_executer_mapping[job_.id].CleanUpWorkDir()
        del self.job_executer_mapping[job_.id]
      # TODO(raymes): remove job from self.all_jobs

  def NotifyJobComplete(self, job_):
    self.machine_manager.ReturnMachines(job_.machines)

    with self._lock:
      self._logger.debug('Handling %r completion event.', job_)

      if job_.status == job.STATUS_SUCCEEDED:
        for succ in job_.successors:
          if succ.is_ready:
            if succ not in self.ready_jobs:
              self.ready_jobs.append(succ)

      self._jobs_available.notifyAll()

  def AddListener(self, listener):
    self.listeners.append(listener)

  @logger.HandleUncaughtExceptions
  def run(self):
    self._logger.info("Started.")

    while not self._exit_request:
      with self._lock:
        # Get the next ready job, block if there are none
        self._jobs_available.wait()

        while self.ready_jobs:
          ready_job = self.ready_jobs.pop()

          required_machines = ready_job.machine_dependencies
          for pred in ready_job.predecessors:
            required_machines[0].AddPreferredMachine(
                pred.primary_machine.hostname)

          machines = self.machine_manager.GetMachines(required_machines)
          if not machines:
            # If we can't get the necessary machines right now, simply wait
            # for some jobs to complete
            self.ready_jobs.insert(0, ready_job)
            break
          else:
            # Mark as executing
            executer = JobExecuter(ready_job, machines, self.listeners)
            executer.start()
            self.job_executer_mapping[ready_job.id] = executer

    self._logger.info("Stopped.")
