#
# Copyright (C) 2008 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 command import PagedCommand

try:
  import threading as _threading
except ImportError:
  import dummy_threading as _threading

import glob

import itertools
import os

from color import Coloring
import platform_utils

class Status(PagedCommand):
  common = True
  helpSummary = "Show the working tree status"
  helpUsage = """
%prog [<project>...]
"""
  helpDescription = """
'%prog' compares the working tree to the staging area (aka index),
and the most recent commit on this branch (HEAD), in each project
specified.  A summary is displayed, one line per file where there
is a difference between these three states.

The -j/--jobs option can be used to run multiple status queries
in parallel.

The -o/--orphans option can be used to show objects that are in
the working directory, but not associated with a repo project.
This includes unmanaged top-level files and directories, but also
includes deeper items.  For example, if dir/subdir/proj1 and
dir/subdir/proj2 are repo projects, dir/subdir/proj3 will be shown
if it is not known to repo.

# Status Display

The status display is organized into three columns of information,
for example if the file 'subcmds/status.py' is modified in the
project 'repo' on branch 'devwork':

  project repo/                                   branch devwork
   -m     subcmds/status.py

The first column explains how the staging area (index) differs from
the last commit (HEAD).  Its values are always displayed in upper
case and have the following meanings:

 -:  no difference
 A:  added         (not in HEAD,     in index                     )
 M:  modified      (    in HEAD,     in index, different content  )
 D:  deleted       (    in HEAD, not in index                     )
 R:  renamed       (not in HEAD,     in index, path changed       )
 C:  copied        (not in HEAD,     in index, copied from another)
 T:  mode changed  (    in HEAD,     in index, same content       )
 U:  unmerged; conflict resolution required

The second column explains how the working directory differs from
the index.  Its values are always displayed in lower case and have
the following meanings:

 -:  new / unknown (not in index,     in work tree                )
 m:  modified      (    in index,     in work tree, modified      )
 d:  deleted       (    in index, not in work tree                )

"""

  def _Options(self, p):
    p.add_option('-j', '--jobs',
                 dest='jobs', action='store', type='int', default=2,
                 help="number of projects to check simultaneously")
    p.add_option('-o', '--orphans',
                 dest='orphans', action='store_true',
                 help="include objects in working directory outside of repo projects")
    p.add_option('-q', '--quiet', action='store_true',
                 help="only print the name of modified projects")

  def _StatusHelper(self, project, clean_counter, sem, quiet):
    """Obtains the status for a specific project.

    Obtains the status for a project, redirecting the output to
    the specified object. It will release the semaphore
    when done.

    Args:
      project: Project to get status of.
      clean_counter: Counter for clean projects.
      sem: Semaphore, will call release() when complete.
      output: Where to output the status.
    """
    try:
      state = project.PrintWorkTreeStatus(quiet=quiet)
      if state == 'CLEAN':
        next(clean_counter)
    finally:
      sem.release()

  def _FindOrphans(self, dirs, proj_dirs, proj_dirs_parents, outstring):
    """find 'dirs' that are present in 'proj_dirs_parents' but not in 'proj_dirs'"""
    status_header = ' --\t'
    for item in dirs:
      if not platform_utils.isdir(item):
        outstring.append(''.join([status_header, item]))
        continue
      if item in proj_dirs:
        continue
      if item in proj_dirs_parents:
        self._FindOrphans(glob.glob('%s/.*' % item) +
            glob.glob('%s/*' % item),
            proj_dirs, proj_dirs_parents, outstring)
        continue
      outstring.append(''.join([status_header, item, '/']))

  def Execute(self, opt, args):
    all_projects = self.GetProjects(args)
    counter = itertools.count()

    if opt.jobs == 1:
      for project in all_projects:
        state = project.PrintWorkTreeStatus(quiet=opt.quiet)
        if state == 'CLEAN':
          next(counter)
    else:
      sem = _threading.Semaphore(opt.jobs)
      threads = []
      for project in all_projects:
        sem.acquire()

        t = _threading.Thread(target=self._StatusHelper,
                              args=(project, counter, sem, opt.quiet))
        threads.append(t)
        t.daemon = True
        t.start()
      for t in threads:
        t.join()
    if not opt.quiet and len(all_projects) == next(counter):
      print('nothing to commit (working directory clean)')

    if opt.orphans:
      proj_dirs = set()
      proj_dirs_parents = set()
      for project in self.GetProjects(None, missing_ok=True):
        proj_dirs.add(project.relpath)
        (head, _tail) = os.path.split(project.relpath)
        while head != "":
          proj_dirs_parents.add(head)
          (head, _tail) = os.path.split(head)
      proj_dirs.add('.repo')

      class StatusColoring(Coloring):
        def __init__(self, config):
          Coloring.__init__(self, config, 'status')
          self.project = self.printer('header', attr = 'bold')
          self.untracked = self.printer('untracked', fg = 'red')

      orig_path = os.getcwd()
      try:
        os.chdir(self.manifest.topdir)

        outstring = []
        self._FindOrphans(glob.glob('.*') +
            glob.glob('*'),
            proj_dirs, proj_dirs_parents, outstring)

        if outstring:
          output = StatusColoring(self.manifest.globalConfig)
          output.project('Objects not within a project (orphans)')
          output.nl()
          for entry in outstring:
            output.untracked(entry)
            output.nl()
        else:
          print('No orphan files or directories')

      finally:
        # Restore CWD.
        os.chdir(orig_path)
