# Copyright (c) 2021 The Regents of the University of California
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from typing import Generator, Optional
import m5.stats
from ..components.processors.abstract_processor import AbstractProcessor
from ..components.processors.switchable_processor import SwitchableProcessor
from m5.util import warn
from pathlib import Path

"""
In this package we store generators for simulation exit events.
"""


def warn_default_decorator(gen: Generator, type: str, effect: str):
    """A decortator for generators which will print a warning that it is a
    default generator.
    """

    def wrapped_generator(*args, **kw_args):
        warn(
            f"No behavior was set by the user for {type}."
            f" Default behavior is {effect}."
        )
        for value in gen(*args, **kw_args):
            yield value

    return wrapped_generator


def exit_generator():
    """
    A default generator for an exit event. It will return True, indicating that
    the Simulator run loop should exit.
    """
    while True:
        yield True


def switch_generator(processor: AbstractProcessor):
    """
    A default generator for a switch exit event. If the processor is a
    SwitchableProcessor, this generator will switch it. Otherwise nothing will
    happen.
    """
    is_switchable = isinstance(processor, SwitchableProcessor)
    while True:
        if is_switchable:
            yield processor.switch()
        else:
            yield False


def dump_reset_generator():
    """
    A generator for doing statstic dump and reset. It will reset the simulation
    statistics and then dump simulation statistics.
    The Simulation run loop will continue after executing the behavior of the
    generator.
    """
    while True:
        m5.stats.dump()
        m5.stats.reset()
        yield False


def save_checkpoint_generator(checkpoint_dir: Optional[Path] = None):
    """
    A generator for taking a checkpoint. It will take a checkpoint with the
    input path and the current simulation Ticks.
    The Simulation run loop will continue after executing the behavior of the
    generator.
    """
    if not checkpoint_dir:
        from m5 import options

        checkpoint_dir = Path(options.outdir)
    while True:
        m5.checkpoint((checkpoint_dir / f"cpt.{str(m5.curTick())}").as_posix())
        yield False


def reset_stats_generator():
    """
    This generator resets the stats every time it is called. It does not dump
    the stats before resetting them.
    """
    while True:
        m5.stats.reset()
        yield False


def dump_stats_generator():
    """
    This generator dumps the stats every time it is called.
    """
    while True:
        m5.stats.dump()
        yield False


def skip_generator():
    """
    This generator does nothing when on the exit event.
    The simulation will continue after this generator.
    """
    while True:
        yield False
