# DExTer : Debugging Experience Tester
# ~~~~~~   ~         ~~         ~   ~~
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

"""DexExpectWatch base class, holds logic for how to build and process expected
 watch commands.
"""

import abc
import difflib
import os

from dex.command.CommandBase import CommandBase
from dex.command.StepValueInfo import StepValueInfo


class DexExpectWatchBase(CommandBase):
    def __init__(self, *args, **kwargs):
        if len(args) < 2:
            raise TypeError('expected at least two args')

        self.expression = args[0]
        self.values = [str(arg) for arg in args[1:]]
        try:
            on_line = kwargs.pop('on_line')
            self._from_line = on_line
            self._to_line = on_line
        except KeyError:
            self._from_line = kwargs.pop('from_line', 1)
            self._to_line = kwargs.pop('to_line', 999999)
        self._require_in_order = kwargs.pop('require_in_order', True)
        if kwargs:
            raise TypeError('unexpected named args: {}'.format(
                ', '.join(kwargs)))

        # Number of times that this watch has been encountered.
        self.times_encountered = 0

        # We'll pop from this set as we encounter values so anything left at
        # the end can be considered as not having been seen.
        self._missing_values = set(self.values)

        self.misordered_watches = []

        # List of StepValueInfos for any watch that is encountered as invalid.
        self.invalid_watches = []

        # List of StepValueInfo any any watch where we couldn't retrieve its
        # data.
        self.irretrievable_watches = []

        # List of StepValueInfos for any watch that is encountered as having
        # been optimized out.
        self.optimized_out_watches = []

        # List of StepValueInfos for any watch that is encountered that has an
        # expected value.
        self.expected_watches = []

        # List of StepValueInfos for any watch that is encountered that has an
        # unexpected value.
        self.unexpected_watches = []

        super(DexExpectWatchBase, self).__init__()


    def get_watches(self):
        return [self.expression]

    @property
    def line_range(self):
        return list(range(self._from_line, self._to_line + 1))

    @property
    def missing_values(self):
        return sorted(list(self._missing_values))

    @property
    def encountered_values(self):
        return sorted(list(set(self.values) - self._missing_values))

    @abc.abstractmethod
    def _get_expected_field(self, watch):
        """Return a field from watch that this ExpectWatch command is checking.
        """

    def _handle_watch(self, step_info):
        self.times_encountered += 1

        if not step_info.watch_info.could_evaluate:
            self.invalid_watches.append(step_info)
            return

        if step_info.watch_info.is_optimized_away:
            self.optimized_out_watches.append(step_info)
            return

        if step_info.watch_info.is_irretrievable:
            self.irretrievable_watches.append(step_info)
            return

        if step_info.expected_value not in self.values:
            self.unexpected_watches.append(step_info)
            return

        self.expected_watches.append(step_info)
        try:
            self._missing_values.remove(step_info.expected_value)
        except KeyError:
            pass

    def _check_watch_order(self, actual_watches, expected_values):
        """Use difflib to figure out whether the values are in the expected order
        or not.
        """
        differences = []
        actual_values = [w.expected_value for w in actual_watches]
        value_differences = list(difflib.Differ().compare(actual_values,
                                                          expected_values))

        missing_value = False
        index = 0
        for vd in value_differences:
            kind = vd[0]
            if kind == '+':
                # A value that is encountered in the expected list but not in the
                # actual list.  We'll keep a note that something is wrong and flag
                # the next value that matches as misordered.
                missing_value = True
            elif kind == ' ':
                # This value is as expected.  It might still be wrong if we've
                # previously encountered a value that is in the expected list but
                #  not the actual list.
                if missing_value:
                    missing_value = False
                    differences.append(actual_watches[index])
                index += 1
            elif kind == '-':
                # A value that is encountered in the actual list but not the
                #  expected list.
                differences.append(actual_watches[index])
                index += 1
            else:
                assert False, 'unexpected diff:{}'.format(vd)

        return differences

    def eval(self, step_collection):
        for step in step_collection.steps:
            loc = step.current_location

            if (loc.path and os.path.exists(loc.path) and
                os.path.exists(self.path) and
                os.path.samefile(loc.path, self.path) and
                loc.lineno in self.line_range):
                try:
                    watch = step.program_state.frames[0].watches[self.expression]
                except KeyError:
                    pass
                else:
                    expected_field = self._get_expected_field(watch)
                    step_info = StepValueInfo(step.step_index, watch, 
                                              expected_field)
                    self._handle_watch(step_info)

        if self._require_in_order:
            # A list of all watches where the value has changed.
            value_change_watches = []
            prev_value = None
            for watch in self.expected_watches:
                if watch.expected_value != prev_value:
                    value_change_watches.append(watch)
                    prev_value = watch.expected_value

            self.misordered_watches = self._check_watch_order(
                value_change_watches, [
                    v for v in self.values if v in
                    [w.expected_value for w in self.expected_watches]
                ])
