#!/usr/bin/env python3
# -*- coding: utf-8 -*-

##############################################################################
#                                                                            #
#  GhIDA: Ghidra decompiler for IDA Pro                                      #
#                                                                            #
#  Copyright 2019 Andrea Marcelli, Cisco Talos                               #
#                                                                            #
#  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.                                            #
#                                                                            #
##############################################################################

import ida_kernwin
import idaapi

from constants import COMMENT_FORM_TEXT
from constants import RENAME_FORM_TEXT
from constants import SETTINGS_FORM_TEXT

# from utility import get_address_for_symbol
from utility import from_ghidra_to_ida_syntax_conversion
from utility import from_ida_to_ghidra_syntax_conversion


USE_GHIDRAAAS_OPTION_CONST = 11
SAVE_CACHE_OPTION_CONST = 4
DO_NOT_SHOW_DIALOG_CONST = 7


# ------------------------------------------------------------
#   SYMBOLS HIGHLIGHTING
# ------------------------------------------------------------

def highlight_symbol_in_DISASM():
    """
    Select a symbol in the DECOMP view,
    highlight the corresponding symbols in IDA DISASM view.
    """
    # print("GhIDA:: [DEBUG] highlight_symbol_in_DISASM called")
    disasm_widget = idaapi.find_widget('IDA View-A')

    symbol = None
    ret = ida_kernwin.get_highlight(ida_kernwin.get_current_viewer())
    if ret and ret[1]:
        symbol = ret[0]

    if not symbol:
        # TODO improve it
        # Highlight a non-existing symbole
        idaapi.set_highlight(disasm_widget, 'aaabbbccc', 1)
        return True

    converted_symbol = from_ghidra_to_ida_syntax_conversion(symbol)
    if converted_symbol:
        # Update IDA DISASM view
        idaapi.set_highlight(disasm_widget, converted_symbol, 1)
    else:
        # TODO improve it
        # Highlight a non-existing symbole
        idaapi.set_highlight(disasm_widget, 'aaabbbccc', 1)
    return True


def highlight_symbol_in_DECOMP():
    """
    Select a symbol in the IDA DISASM view,
    highlight the corresponding symbol in DECOMP view.
    """
    # print("GhIDA:: [DEBUG] highlight_symbol_in_DECOMP called")
    symbol = None
    ret = ida_kernwin.get_highlight(ida_kernwin.get_current_viewer())
    if ret and ret[1]:
        symbol = ret[0]

    if not symbol:
        return

    converted_symbol = from_ida_to_ghidra_syntax_conversion(symbol)
    decompiler_widget = idaapi.find_widget('Decompiled Function')
    if converted_symbol:
        # Update IDA DECOMP view
        idaapi.set_highlight(decompiler_widget, converted_symbol, 1)
    else:
        idaapi.set_highlight(decompiler_widget, 'aaabbbccc', 1)
    return


# ------------------------------------------------------------
#   RENAME SYMBOLS FORM & utils
# ------------------------------------------------------------

class RenameForm(ida_kernwin.Form):

    def __init__(self, address, current_name):
        """
        Display a Pop-Up and get a new name for the symbol
        """
        self.invert = False
        rename_form_dict = {
            'cAddr': ida_kernwin.Form.NumericLabel(address,
                                                   ida_kernwin.Form.FT_ADDR),
            'cLbl': ida_kernwin.Form.StringLabel(current_name),
            'iStr': ida_kernwin.Form.StringInput(),
        }
        ida_kernwin.Form.__init__(self, RENAME_FORM_TEXT, rename_form_dict)


def display_rename_form(address, current_name):
    """
    Display the Pop-Up and return the new name
    """
    new_name = None
    f = RenameForm(address, current_name)
    f.Compile()
    if f.Execute() == 1:
        new_name = f.iStr.value
    f.Free()
    return new_name


# ------------------------------------------------------------
#   Add comment FORM
# ------------------------------------------------------------

class CommentForm(ida_kernwin.Form):

    def __init__(self, text):
        """
        Display a Pop-Up and get a new name for the symbol
        """
        self.invert = False
        comment_form_dict = {
            'iStr': ida_kernwin.Form.MultiLineTextControl(
                text=text,
                swidth=125,
                flags=ida_kernwin.Form.MultiLineTextControl.TXTF_FIXEDFONT)
        }
        ida_kernwin.Form.__init__(self,
                                  COMMENT_FORM_TEXT,
                                  comment_form_dict)


def display_comment_form(text):
    """
    Display the Pop-Up and return the new name
    """
    comment = None
    f = CommentForm(text)
    f.Compile()
    if f.Execute() == 1:
        comment = f.iStr.text
    f.Free()
    return comment


# ------------------------------------------------------------
#   SETTINGS FORM
# ------------------------------------------------------------

class GhIDASettingsForm(ida_kernwin.Form):

    def __init__(self):
        dd = {
            'FormChangeCall': ida_kernwin.Form.FormChangeCb(self.OnFormChange),
            'cGroup': ida_kernwin.Form.ChkGroupControl(("GLocal", "GRe")),
            'GhidraInstallationPath': ida_kernwin.Form.DirInput(),
            'GhidraaasURL': ida_kernwin.Form.StringInput(),
            'cGroup1': ida_kernwin.Form.ChkGroupControl(("GLocal1", "GRe1")),
            'cGroup2': ida_kernwin.Form.ChkGroupControl(("GLocal2", "GRe2"))
        }
        ida_kernwin.Form.__init__(self, SETTINGS_FORM_TEXT, dd)
        self.ghidraaas_selected = False
        self.save_cache = True
        self.show_dialog = True

    def OnFormChange(self, fid):
        if fid == -1:
            self.EnableField(self.GhidraInstallationPath, True)
            self.EnableField(self.GhidraaasURL, False)

        # USE GHIDRAAAS OPTION
        if fid == USE_GHIDRAAAS_OPTION_CONST:
            if self.ghidraaas_selected:
                self.EnableField(self.GhidraInstallationPath, True)
                self.EnableField(self.GhidraaasURL, False)
                self.ghidraaas_selected = False

            else:
                self.EnableField(self.GhidraInstallationPath, False)
                self.EnableField(self.GhidraaasURL, True)
                self.ghidraaas_selected = True

        # SAVE / LOAD CACHE
        if fid == SAVE_CACHE_OPTION_CONST:
            if self.save_cache:
                self.save_chache = False
            else:
                self.save_cache = True

        # DO NOT SHOW DIALOG
        if fid == DO_NOT_SHOW_DIALOG_CONST:
            if self.show_dialog:
                self.show_dialog = False
            else:
                self.show_dialog = True

        return 1