# -*- encoding: utf-8 -*-
# Copyright 2014 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.

"""Provides objects for reading and writing raw data to and from steps."""

from recipe_engine import recipe_api
from recipe_engine import util as recipe_util

import codecs
import contextlib
import cStringIO
import os
import shutil
import sys
import tempfile


def _rmfile(p):  # pragma: no cover
  """Deletes a file, even a read-only one on Windows."""
  if sys.platform == 'win32':
    try:
      os.remove(p)
    except OSError:
      # Try to remove the read-only bit and remove again.
      os.chmod(p, 0777)
      os.remove(p)
  else:
    os.remove(p)


def _rmtree(d):  # pragma: no cover
  """Deletes a directory without throwing, even one with read-only files."""
  if not os.path.exists(d):
    return

  if sys.platform == 'win32':
    # Tested manually.
    def unset_ro_and_remove_again(fn, p, excinfo):
      """Removes file even if it has the READ_ONLY file attribute.

      On Windows, a file with the READ_ONLY file attribute cannot be deleted.
      This is different than on POSIX where only the containing directory ACL
      matters.

      shutil.rmtree() has trouble with this. Helps it a bit.
      """
      # fn is one of islink, listdir, remove or rmdir.
      if fn is os.remove:
        # Try to remove the read-only bit.
        os.chmod(p, 0777)
        # And remove again.
        os.remove(p)
        return
      # Reraise the original exception.
      raise excinfo[0], excinfo[1], excinfo[2]

    # On Windows, some paths exceed MAX_PATH. Work around this by prepending
    # the UNC magic prefix '\\?\' which allows the Windows API file calls to
    # ignore the MAX_PATH limit.
    shutil.rmtree(ur'\\?\%s' % (d,), onerror=unset_ro_and_remove_again)
  else:
    shutil.rmtree(d)


class InputDataPlaceholder(recipe_util.InputPlaceholder):
  def __init__(self, data, suffix, name=None):
    if not isinstance(data, str): # pragma: no cover
      raise TypeError(
        "Data passed to InputDataPlaceholder was %r, expected 'str'"
        % (type(data).__name__))
    self.data = data
    self.suffix = suffix
    self._backing_file = None
    super(InputDataPlaceholder, self).__init__(name=name)

  @property
  def backing_file(self):
    return self._backing_file

  def render(self, test):
    assert not self._backing_file, 'Placeholder can be used only once'
    if test.enabled:
      # cheat and pretend like we're going to pass the data on the
      # cmdline for test expectation purposes.
      with contextlib.closing(cStringIO.StringIO()) as output:
        self.write_encoded_data(output)
        self._backing_file = output.getvalue()
    else:  # pragma: no cover
      input_fd, self._backing_file = tempfile.mkstemp(suffix=self.suffix)
      with os.fdopen(os.dup(input_fd), 'wb') as f:
        self.write_encoded_data(f)
      os.close(input_fd)
    return [self._backing_file]

  def cleanup(self, test_enabled):
    assert self._backing_file is not None
    if not test_enabled:  # pragma: no cover
      try:
        _rmfile(self._backing_file)
      except OSError:
        pass
    self._backing_file = None

  def write_encoded_data(self, f):
    """ Encodes data to be written out, when rendering this placeholder.
    """
    f.write(self.data)


class InputTextPlaceholder(InputDataPlaceholder):
  """ A input placeholder which expects to write out text.
  """
  def __init__(self, data, suffix, name=None):
    super(InputTextPlaceholder, self).__init__(data, suffix, name=name)
    assert isinstance(data, basestring)

  def write_encoded_data(self, f):
    # Sometimes users give us invalid utf-8 data. They shouldn't, but it does
    # happen every once and a while. Just ignore it, and replace with �.
    # We're assuming users only want to write text data out.
    # self.data can be large, so be careful to do the conversion in chunks
    # while streaming the data out, instead of requiring a full copy.
    n = 1 << 16
    # This is a generator expression, so this only copies one chunk of
    # self.data at any one time.
    chunks = (self.data[i:i + n] for i in xrange(0, len(self.data), n))
    decoded = codecs.iterdecode(chunks, 'utf-8', 'replace')
    for chunk in codecs.iterencode(decoded, 'utf-8'):
      f.write(chunk)


class OutputDataPlaceholder(recipe_util.OutputPlaceholder):
  def __init__(self, suffix, leak_to, name=None, add_output_log=False):
    assert add_output_log in (True, False, 'on_failure'), (
        'add_output_log=%r' % add_output_log)
    self.suffix = suffix
    self.leak_to = leak_to
    self.add_output_log = add_output_log
    self._backing_file = None
    super(OutputDataPlaceholder, self).__init__(name=name)

  @property
  def backing_file(self):
    return self._backing_file

  def render(self, test):
    assert not self._backing_file, 'Placeholder can be used only once'
    if self.leak_to:
      self._backing_file = str(self.leak_to)
      return [self._backing_file]
    if test.enabled:
      self._backing_file = '/path/to/tmp/' + self.suffix.lstrip('.')
    else:  # pragma: no cover
      output_fd, self._backing_file = tempfile.mkstemp(suffix=self.suffix)
      os.close(output_fd)
    return [self._backing_file]

  def result(self, presentation, test):
    assert self._backing_file
    ret = None
    if test.enabled:
      self._backing_file = None
      with contextlib.closing(cStringIO.StringIO(test.data or '')) as infile:
        ret = self.read_decoded_data(infile)
    else:  # pragma: no cover
      try:
        with open(self._backing_file, 'rb') as f:
          ret = self.read_decoded_data(f)
      finally:
        if not self.leak_to:
          _rmfile(self._backing_file)
        self._backing_file = None

    if ret is not None and (
        self.add_output_log is True or
        (self.add_output_log == 'on_failure' and
         presentation.status != 'SUCCESS')):
      presentation.logs[self.label] = ret.splitlines()

    return ret

  def read_decoded_data(self, f):
    """ Decodes data to be read in, when getting the result of this placeholder.
    """
    return f.read()


class OutputTextPlaceholder(OutputDataPlaceholder):
  """ A output placeholder which expects to write out text.
  """
  def read_decoded_data(self, f):
    # This ensures that the raw result bytes we got are, in fact, valid utf-8,
    # replacing invalid bytes with �. Because python2's unicode support is
    # wonky, we re-encode the now-valid-utf-8 back into a str object so that
    # users don't need to deal with `unicode` objects.
    # The file contents can be large, so be careful to do the conversion in
    # chunks while streaming the data in, instead of requiring a full copy.
    n = 1 << 16
    chunks = iter(lambda: f.read(n), '')
    decoded = codecs.iterdecode(chunks, 'utf-8', 'replace')
    return ''.join(codecs.iterencode(decoded, 'utf-8'))

class OutputDataDirPlaceholder(recipe_util.OutputPlaceholder):
  def __init__(self, suffix, leak_to, name=None):
    self.suffix = suffix
    self.leak_to = leak_to
    self._backing_dir = None
    super(OutputDataDirPlaceholder, self).__init__(name=name)

  @property
  def backing_file(self):  # pragma: no cover
    raise ValueError('Output dir placeholders can not be used for stdin, '
                     'stdout or stderr')

  def render(self, test):
    assert not self._backing_dir, 'Placeholder can be used only once'
    if self.leak_to:
      self._backing_dir = str(self.leak_to)
      if not test.enabled: # pragma: no cover
        if not os.path.exists(self._backing_dir):
          os.makedirs(self._backing_dir)
    else:
      if not test.enabled: # pragma: no cover
        self._backing_dir = tempfile.mkdtemp(suffix=self.suffix)
      else:
        self._backing_dir = '/path/to/tmp/' + self.suffix

    return [self._backing_dir]

  def result(self, presentation, test):
    assert self._backing_dir
    if test.enabled:
      self._backing_dir = None
      return test.data or {}
    else:  # pragma: no cover
      try:
        all_files = {}
        for dir_path, _, files in os.walk(self._backing_dir):
          for filename in files:
            abs_path = os.path.join(dir_path, filename)
            rel_path = os.path.relpath(abs_path, self._backing_dir)
            if sys.platform == 'win32':
              abs_path = ur'\\?\%s' % (abs_path,)
            with open(abs_path, 'rb') as f:
              all_files[rel_path] = f.read()
        return all_files
      finally:
        if not self.leak_to:
          _rmtree(self._backing_dir)
        self._backing_dir = None


class RawIOApi(recipe_api.RecipeApi):
  @recipe_util.returns_placeholder
  @staticmethod
  def input(data, suffix='', name=None):
    """Returns a Placeholder for use as a step argument.

    This placeholder can be used to pass data to steps. The recipe engine will
    dump the 'data' into a file, and pass the filename to the command line
    argument.

    data MUST be of type 'str' (not basestring, not unicode).

    If 'suffix' is not '', it will be used when the engine calls
    tempfile.mkstemp.

    See examples/full.py for usage example.
    """
    return InputDataPlaceholder(data, suffix, name=name)

  @recipe_util.returns_placeholder
  @staticmethod
  def input_text(data, suffix='', name=None):
    """Returns a Placeholder for use as a step argument.

    data MUST be of type 'str' (not basestring, not unicode). The str is
    expected to have valid utf-8 data in it.

    Similar to input(), but ensures that 'data' is valid utf-8 text. Any
    non-utf-8 characters will be replaced with �.
    """
    return InputTextPlaceholder(data, suffix, name=name)

  @recipe_util.returns_placeholder
  @staticmethod
  def output(suffix='', leak_to=None, name=None, add_output_log=False):
    """Returns a Placeholder for use as a step argument, or for std{out,err}.

    If 'leak_to' is None, the placeholder is backed by a temporary file with
    a suffix 'suffix'. The file is deleted when the step finishes.

    If 'leak_to' is not None, then it should be a Path and placeholder
    redirects IO to a file at that path. Once step finishes, the file is
    NOT deleted (i.e. it's 'leaking'). 'suffix' is ignored in that case.

    Args:
       * add_output_log (True|False|'on_failure') - Log a copy of the output
         to a step link named `name`. If this is 'on_failure', only create this
         log when the step has a non-SUCCESS status.
    """
    return OutputDataPlaceholder(suffix, leak_to, name=name,
                                 add_output_log=add_output_log)

  @recipe_util.returns_placeholder
  @staticmethod
  def output_text(suffix='', leak_to=None, name=None, add_output_log=False):
    """Returns a Placeholder for use as a step argument, or for std{out,err}.

    Similar to output(), but uses an OutputTextPlaceholder, which expects utf-8
    encoded text.
    Similar to input(), but tries to decode the resulting data as utf-8 text,
    replacing any decoding errors with �.

    Args:
       * add_output_log (True|False|'on_failure') - Log a copy of the output
         to a step link named `name`. If this is 'on_failure', only create this
         log when the step has a non-SUCCESS status.
    """
    return OutputTextPlaceholder(suffix, leak_to, name=name,
                                 add_output_log=add_output_log)

  @recipe_util.returns_placeholder
  @staticmethod
  def output_dir(suffix='', leak_to=None, name=None):
    """Returns a directory Placeholder for use as a step argument.

    If 'leak_to' is None, the placeholder is backed by a temporary dir with
    a suffix 'suffix'. The dir is deleted when the step finishes.

    If 'leak_to' is not None, then it should be a Path and placeholder
    redirects IO to a dir at that path. Once step finishes, the dir is
    NOT deleted (i.e. it's 'leaking'). 'suffix' is ignored in that case.
    """
    return OutputDataDirPlaceholder(suffix, leak_to, name=name)
