# 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.

"""Logic for tracing repo interactions.

Activated via `repo --trace ...` or `REPO_TRACE=1 repo ...`.

Temporary: Tracing is always on. Set `REPO_TRACE=0` to turn off.
To also include trace outputs in stderr do `repo --trace_to_stderr ...`
"""

import sys
import os
import time
from contextlib import ContextDecorator

import platform_utils

# Env var to implicitly turn on tracing.
REPO_TRACE = 'REPO_TRACE'

# Temporarily set tracing to always on unless user expicitly sets to 0.
_TRACE = os.environ.get(REPO_TRACE) != '0'
_TRACE_TO_STDERR = False
_TRACE_FILE = None
_TRACE_FILE_NAME = 'TRACE_FILE'
_MAX_SIZE = 70  # in mb
_NEW_COMMAND_SEP = '+++++++++++++++NEW COMMAND+++++++++++++++++++'


def IsTraceToStderr():
  return _TRACE_TO_STDERR


def IsTrace():
  return _TRACE


def SetTraceToStderr():
  global _TRACE_TO_STDERR
  _TRACE_TO_STDERR = True


def SetTrace():
  global _TRACE
  _TRACE = True


def _SetTraceFile(quiet):
  global _TRACE_FILE
  _TRACE_FILE = _GetTraceFile(quiet)


class Trace(ContextDecorator):

  def _time(self):
    """Generate nanoseconds of time in a py3.6 safe way"""
    return int(time.time() * 1e+9)

  def __init__(self, fmt, *args, first_trace=False, quiet=True):
    """Initialize the object.

    Args:
      fmt: The format string for the trace.
      *args: Arguments to pass to formatting.
      first_trace: Whether this is the first trace of a `repo` invocation.
      quiet: Whether to suppress notification of trace file location.
    """
    if not IsTrace():
      return
    self._trace_msg = fmt % args

    if not _TRACE_FILE:
      _SetTraceFile(quiet)

    if first_trace:
      _ClearOldTraces()
      self._trace_msg = f'{_NEW_COMMAND_SEP} {self._trace_msg}'

  def __enter__(self):
    if not IsTrace():
      return self

    print_msg = f'PID: {os.getpid()} START: {self._time()} :{self._trace_msg}\n'

    with open(_TRACE_FILE, 'a') as f:
      print(print_msg, file=f)

    if _TRACE_TO_STDERR:
      print(print_msg, file=sys.stderr)

    return self

  def __exit__(self, *exc):
    if not IsTrace():
      return False

    print_msg = f'PID: {os.getpid()} END: {self._time()} :{self._trace_msg}\n'

    with open(_TRACE_FILE, 'a') as f:
      print(print_msg, file=f)

    if _TRACE_TO_STDERR:
      print(print_msg, file=sys.stderr)

    return False


def _GetTraceFile(quiet):
  """Get the trace file or create one."""
  # TODO: refactor to pass repodir to Trace.
  repo_dir = os.path.dirname(os.path.dirname(__file__))
  trace_file = os.path.join(repo_dir, _TRACE_FILE_NAME)
  if not quiet:
    print(f'Trace outputs in {trace_file}', file=sys.stderr)
  return trace_file


def _ClearOldTraces():
  """Clear the oldest commands if trace file is too big.

  Note: If the trace file contains output from two `repo`
        commands that were running at the same time, this
        will not work precisely.
  """
  if os.path.isfile(_TRACE_FILE):
    while os.path.getsize(_TRACE_FILE) / (1024 * 1024) > _MAX_SIZE:
      temp_file = _TRACE_FILE + '.tmp'
      with open(_TRACE_FILE, 'r', errors='ignore') as fin:
        with open(temp_file, 'w') as tf:
          trace_lines = fin.readlines()
          for i, l in enumerate(trace_lines):
            if 'END:' in l and _NEW_COMMAND_SEP in l:
              tf.writelines(trace_lines[i + 1:])
              break
      platform_utils.rename(temp_file, _TRACE_FILE)
