#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#

"""A profiler context manager based on cProfile.Profile and guppy.hpy objects.

For internal use only; no backwards-compatibility guarantees.
"""

# pytype: skip-file
# mypy: check-untyped-defs

import cProfile
import io
import logging
import os
import pstats
import random
import tempfile
import time
from typing import Callable
from typing import Optional

from apache_beam.io import filesystems

_LOGGER = logging.getLogger(__name__)


class Profile(object):
  """cProfile and Heapy wrapper context for saving and logging profiler
  results."""

  SORTBY = 'cumulative'

  profile_output: str
  stats: pstats.Stats

  def __init__(
      self,
      profile_id: str,
      profile_location: Optional[str] = None,
      log_results: bool = False,
      file_copy_fn: Optional[Callable[[str, str], None]] = None,
      time_prefix: str = '%Y-%m-%d_%H_%M_%S-',
      enable_cpu_profiling: bool = False,
      enable_memory_profiling: bool = False,
  ):
    """Creates a Profile object.

    Args:
      profile_id: Unique id of the profiling session.
      profile_location: The file location where the profiling results will be
        stored.
      log_results: Log the result to console if true.
      file_copy_fn: Lambda function for copying files.
      time_prefix: Format of the timestamp prefix in profiling result files.
      enable_cpu_profiling: CPU profiler will be enabled during the profiling
        session.
      enable_memory_profiling: Memory profiler will be enabled during the
        profiling session, the profiler only records the newly allocated objects
        in this session.
    """
    self.profile_id = str(profile_id)
    self.profile_location = profile_location
    self.log_results = log_results
    self.file_copy_fn = file_copy_fn or self.default_file_copy_fn
    self.time_prefix = time_prefix
    self.enable_cpu_profiling = enable_cpu_profiling
    self.enable_memory_profiling = enable_memory_profiling

  def __enter__(self):
    _LOGGER.info('Start profiling: %s', self.profile_id)
    if self.enable_cpu_profiling:
      self.profile = cProfile.Profile()
      self.profile.enable()
    if self.enable_memory_profiling:
      try:
        from guppy import hpy
        self.hpy = hpy()
        self.hpy.setrelheap()
      except ImportError:
        _LOGGER.info("Unable to import guppy for memory profiling")
        self.hpy = None
    return self

  def __exit__(self, *args):
    _LOGGER.info('Stop profiling: %s', self.profile_id)

    if self.profile_location:
      if self.enable_cpu_profiling:
        self.profile.create_stats()
        self.profile_output = self._upload_profile_data(
            # typing: seems stats attr is missing from typeshed
            self.profile_location,
            'cpu_profile',
            self.profile.stats)

      if self.enable_memory_profiling:
        if not self.hpy:
          pass
        else:
          h = self.hpy.heap()
          heap_dump_data = '%s\n%s' % (h, h.more)
          self._upload_profile_data(
              self.profile_location,
              'memory_profile',
              heap_dump_data,
              write_binary=False)

    if self.log_results:
      if self.enable_cpu_profiling:
        s = io.StringIO()
        self.stats = pstats.Stats(
            self.profile, stream=s).sort_stats(Profile.SORTBY)
        self.stats.print_stats()
        _LOGGER.info('Cpu profiler data: [%s]', s.getvalue())
      if self.enable_memory_profiling and self.hpy:
        _LOGGER.info('Memory profiler data: \n%s' % self.hpy.heap())

  @staticmethod
  def default_file_copy_fn(src, dest):
    dest_handle = filesystems.FileSystems.create(dest + '.tmp')
    try:
      with open(src, 'rb') as src_handle:
        dest_handle.write(src_handle.read())
    finally:
      dest_handle.close()
    filesystems.FileSystems.rename([dest + '.tmp'], [dest])

  @staticmethod
  def factory_from_options(options) -> Optional[Callable[..., 'Profile']]:
    if options.profile_cpu or options.profile_memory:

      def create_profiler(profile_id, **kwargs):
        if random.random() < options.profile_sample_rate:
          return Profile(
              profile_id,
              options.profile_location,
              enable_cpu_profiling=options.profile_cpu,
              enable_memory_profiling=options.profile_memory,
              **kwargs)

      return create_profiler
    return None

  def _upload_profile_data(
      self, profile_location, dir, data, write_binary=True) -> str:
    dump_location = os.path.join(
        profile_location,
        dir,
        time.strftime(self.time_prefix + self.profile_id))
    fd, filename = tempfile.mkstemp()
    try:
      os.close(fd)
      if write_binary:
        with open(filename, 'wb') as fb:
          import marshal
          marshal.dump(data, fb)
      else:
        with open(filename, 'w') as f:
          f.write(data)
      _LOGGER.info('Copying profiler data to: [%s]', dump_location)
      self.file_copy_fn(filename, dump_location)
    finally:
      os.remove(filename)

    return dump_location
