# 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
"""Interface for communicating with the Visual Studio debugger via DTE."""

import abc
import imp
import os
import sys
from pathlib import PurePath
from collections import namedtuple
from collections import defaultdict

from dex.debugger.DebuggerBase import DebuggerBase
from dex.dextIR import FrameIR, LocIR, StepIR, StopReason, ValueIR
from dex.dextIR import StackFrame, SourceLocation, ProgramState
from dex.utils.Exceptions import Error, LoadDebuggerException
from dex.utils.ReturnCode import ReturnCode


def _load_com_module():
    try:
        module_info = imp.find_module(
            'ComInterface',
            [os.path.join(os.path.dirname(__file__), 'windows')])
        return imp.load_module('ComInterface', *module_info)
    except ImportError as e:
        raise LoadDebuggerException(e, sys.exc_info())


# VSBreakpoint(path: PurePath, line: int, col: int, cond: str).  This is enough
# info to identify breakpoint equivalence in visual studio based on the
# properties we set through dexter currently.
VSBreakpoint = namedtuple('VSBreakpoint', 'path, line, col, cond')

class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta):  # pylint: disable=abstract-method

    # Constants for results of Debugger.CurrentMode
    # (https://msdn.microsoft.com/en-us/library/envdte.debugger.currentmode.aspx)
    dbgDesignMode = 1
    dbgBreakMode = 2
    dbgRunMode = 3

    def __init__(self, *args):
        self.com_module = None
        self._debugger = None
        self._solution = None
        self._fn_step = None
        self._fn_go = None
        # The next available unique breakpoint id. Use self._get_next_id().
        self._next_bp_id = 0
        # VisualStudio appears to common identical breakpoints. That is, if you
        # ask for a breakpoint that already exists the Breakpoints list will
        # not grow. DebuggerBase requires all breakpoints have a unique id,
        # even for duplicates, so we'll need to do some bookkeeping.  Map
        # {VSBreakpoint: list(id)} where id is the unique dexter-side id for
        # the requested breakpoint.
        self._vs_to_dex_ids = defaultdict(list)
        # Map {id: VSBreakpoint} where id is unique and VSBreakpoint identifies
        # a breakpoint in Visual Studio. There may be many ids mapped to a
        # single VSBreakpoint. Use self._vs_to_dex_ids to find (dexter)
        # breakpoints mapped to the same visual studio breakpoint.
        self._dex_id_to_vs = {}

        super(VisualStudio, self).__init__(*args)

    def _custom_init(self):
        try:
            self._debugger = self._interface.Debugger
            self._debugger.HexDisplayMode = False

            self._interface.MainWindow.Visible = (
                self.context.options.show_debugger)

            self._solution = self._interface.Solution
            self._solution.Create(self.context.working_directory.path,
                                  'DexterSolution')

            try:
                self._solution.AddFromFile(self._project_file)
            except OSError:
                raise LoadDebuggerException(
                    'could not debug the specified executable', sys.exc_info())

            self._fn_step = self._debugger.StepInto
            self._fn_go = self._debugger.Go

        except AttributeError as e:
            raise LoadDebuggerException(str(e), sys.exc_info())

    def _custom_exit(self):
        if self._interface:
            self._interface.Quit()

    @property
    def _project_file(self):
        return self.context.options.executable

    @abc.abstractproperty
    def _dte_version(self):
        pass

    @property
    def _location(self):
        #TODO: Find a better way of determining path, line and column info
        # that doesn't require reading break points. This method requires
        # all lines to have a break point on them.
        bp = self._debugger.BreakpointLastHit
        return {
            'path': getattr(bp, 'File', None),
            'lineno': getattr(bp, 'FileLine', None),
            'column': getattr(bp, 'FileColumn', None)
        }

    @property
    def _mode(self):
        return self._debugger.CurrentMode

    def _load_interface(self):
        self.com_module = _load_com_module()
        return self.com_module.DTE(self._dte_version)

    @property
    def version(self):
        try:
            return self._interface.Version
        except AttributeError:
            return None

    def clear_breakpoints(self):
        for bp in self._debugger.Breakpoints:
            bp.Delete()
        self._vs_to_dex_ids.clear()
        self._dex_id_to_vs.clear()

    def _add_breakpoint(self, file_, line):
        return self._add_conditional_breakpoint(file_, line, '')

    def _get_next_id(self):
        # "Generate" a new unique id for the breakpoint.
        id = self._next_bp_id
        self._next_bp_id += 1
        return id

    def _add_conditional_breakpoint(self, file_, line, condition):
        col = 1
        vsbp = VSBreakpoint(PurePath(file_), line, col, condition)
        new_id = self._get_next_id()

        # Do we have an exact matching breakpoint already?
        if vsbp in self._vs_to_dex_ids:
            self._vs_to_dex_ids[vsbp].append(new_id)
            self._dex_id_to_vs[new_id] = vsbp
            return new_id

        # Breakpoint doesn't exist already. Add it now.
        count_before = self._debugger.Breakpoints.Count
        self._debugger.Breakpoints.Add('', file_, line, col, condition)
        # Our internal representation of VS says that the breakpoint doesn't
        # already exist so we do not expect this operation to fail here.
        assert count_before < self._debugger.Breakpoints.Count
        # We've added a new breakpoint, record its id.
        self._vs_to_dex_ids[vsbp].append(new_id)
        self._dex_id_to_vs[new_id] = vsbp
        return new_id

    def get_triggered_breakpoint_ids(self):
        """Returns a set of opaque ids for just-triggered breakpoints.
        """
        bps_hit = self._debugger.AllBreakpointsLastHit
        bp_id_list = []
        # Intuitively, AllBreakpointsLastHit breakpoints are the last hit
        # _bound_ breakpoints. A bound breakpoint's parent holds the info of
        # the breakpoint the user requested. Our internal state tracks the user
        # requested breakpoints so we look at the Parent of these triggered
        # breakpoints to determine which have been hit.
        for bp in bps_hit:
            # All bound breakpoints should have the user-defined breakpoint as
            # a parent.
            assert bp.Parent
            vsbp = VSBreakpoint(PurePath(bp.Parent.File), bp.Parent.FileLine,
                                bp.Parent.FileColumn, bp.Parent.Condition)
            try:
                ids = self._vs_to_dex_ids[vsbp]
            except KeyError:
                pass
            else:
                bp_id_list += ids
        return set(bp_id_list)

    def delete_breakpoint(self, id):
        """Delete a breakpoint by id.

        Raises a KeyError if no breakpoint with this id exists.
        """
        vsbp = self._dex_id_to_vs[id]

        # Remove our id from the associated list of dex ids.
        self._vs_to_dex_ids[vsbp].remove(id)
        del self._dex_id_to_vs[id]

        # Bail if there are other uses of this vsbp.
        if len(self._vs_to_dex_ids[vsbp]) > 0:
            return
        # Otherwise find and delete it.
        for bp in self._debugger.Breakpoints:
            # We're looking at the user-set breakpoints so there shouild be no
            # Parent.
            assert bp.Parent == None
            this_vsbp = VSBreakpoint(PurePath(bp.File), bp.FileLine,
                                     bp.FileColumn, bp.Condition)
            if vsbp == this_vsbp:
                bp.Delete()
                break

    def launch(self):
        self._fn_go()

    def step(self):
        self._fn_step()

    def go(self) -> ReturnCode:
        self._fn_go()
        return ReturnCode.OK

    def set_current_stack_frame(self, idx: int = 0):
        thread = self._debugger.CurrentThread
        stack_frames = thread.StackFrames
        try:
            stack_frame = stack_frames[idx]
            self._debugger.CurrentStackFrame = stack_frame.raw
        except IndexError:
            raise Error('attempted to access stack frame {} out of {}'
                .format(idx, len(stack_frames)))

    def _get_step_info(self, watches, step_index):
        thread = self._debugger.CurrentThread
        stackframes = thread.StackFrames

        frames = []
        state_frames = []


        for idx, sf in enumerate(stackframes):
            frame = FrameIR(
                function=self._sanitize_function_name(sf.FunctionName),
                is_inlined=sf.FunctionName.startswith('[Inline Frame]'),
                loc=LocIR(path=None, lineno=None, column=None))

            fname = frame.function or ''  # pylint: disable=no-member
            if any(name in fname for name in self.frames_below_main):
                break


            state_frame = StackFrame(function=frame.function,
                                     is_inlined=frame.is_inlined,
                                     watches={})

            for watch in watches:
                state_frame.watches[watch] = self.evaluate_expression(
                    watch, idx)


            state_frames.append(state_frame)
            frames.append(frame)

        loc = LocIR(**self._location)
        if frames:
            frames[0].loc = loc
            state_frames[0].location = SourceLocation(**self._location)

        reason = StopReason.BREAKPOINT
        if loc.path is None:  # pylint: disable=no-member
            reason = StopReason.STEP

        program_state = ProgramState(frames=state_frames)

        return StepIR(
            step_index=step_index, frames=frames, stop_reason=reason,
            program_state=program_state)

    @property
    def is_running(self):
        return self._mode == VisualStudio.dbgRunMode

    @property
    def is_finished(self):
        return self._mode == VisualStudio.dbgDesignMode

    @property
    def frames_below_main(self):
        return [
            '[Inline Frame] invoke_main', '__scrt_common_main_seh',
            '__tmainCRTStartup', 'mainCRTStartup'
        ]

    def evaluate_expression(self, expression, frame_idx=0) -> ValueIR:
        self.set_current_stack_frame(frame_idx)
        result = self._debugger.GetExpression(expression)
        self.set_current_stack_frame(0)
        value = result.Value

        is_optimized_away = any(s in value for s in [
            'Variable is optimized away and not available',
            'Value is not available, possibly due to optimization',
        ])

        is_irretrievable = any(s in value for s in [
            '???',
            '<Unable to read memory>',
        ])

        # an optimized away value is still counted as being able to be
        # evaluated.
        could_evaluate = (result.IsValidValue or is_optimized_away
                          or is_irretrievable)

        return ValueIR(
            expression=expression,
            value=value,
            type_name=result.Type,
            error_string=None,
            is_optimized_away=is_optimized_away,
            could_evaluate=could_evaluate,
            is_irretrievable=is_irretrievable,
        )
