from __future__ import annotations
import re
from .androidcore import _AndroidCore
from ...logger import _logger
from ...out import GreppedOut
from .constants import _GrepConstants, _Trackers


class _OtherAnalysis(_AndroidCore, _GrepConstants, _Trackers):

    def all_other_analysis(self):
        """
        Property runs all available checks in _OtherAnalysis

        :return: Dictionary of all other analysis
        :rtype: dict

        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.all_other_analysis()
        """
        methods = [p for p in vars(
            _OtherAnalysis).keys() if not p.startswith('_')]
        [getattr(self, m)() for m in methods if m != 'all_other_analysis']
        self.log_debug('')
        return self._android_findings['other_analysis']

    @_logger
    def other_email_addresses(self, show_code=False) -> GreppedOut:
        """
        Find email addresses in the decompiled source

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_email_addresses()
        """
        regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b'
        grep = self._run_rg(regex=regex, code=show_code)
        match = self._process_match(grep)
        self._other_analysis['email'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_unicode_chars(self, script: str='Hangul', show_code=False):
        """
        Find unicode characters representing differnt character sets from 
        different languages in the decompiled apk. Supports both Unicode 
        Scripes and Unicode Blocks. See the reference for supported ranges. 
        | `Reference <https://www.regular-expressions.info/unicode.html>`__

        Parameters
        ----------
        script : string, default Hangul
            Any supported Unicode Script or Unicode Blocks. Ex: ``Han`` for Chinese characters.
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_chinese_chars()
        """
        regex = r'[\p{' + script + '}]+'
        g = self._run_rg(regex=regex, code=show_code)
        match = self._process_match(g)
        self._other_analysis['chinese'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_ip_address(self, show_code=False) -> GreppedOut:
        """
        Find IP addresses in the decompiled source

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_ip_address()
        """
        regex = r'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b'
        g = self._run_rg(regex=regex, code=show_code)
        match = self._process_match(g)
        self._other_analysis['ipaddress'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_http_urls(self, show_code=False) -> GreppedOut:
        """
        Find HTTP urls in the decompiled source

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_http_urls()
        """
        regex = r'(?:http://)[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[.]@&\(\)\*\+]+'
        g = self._run_rg(regex=regex, code=show_code)
        match = self._process_match(g, is_url=True)
        self._other_analysis['http_url'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_all_urls(self, show_code=False) -> GreppedOut:
        """
        Find all urls in the decompiled source

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_all_urls()
        """
        regex = r'(?:http(s)?://)[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[.]@&\(\)\*\+]+|https?://localhost:?(\d+)?'
        g = self._run_rg(regex=regex, code=show_code)
        match = self._process_match(g, is_url=True)
        self._other_analysis['urls'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_file_urlhandler(self, show_code=False) -> GreppedOut:
        """
        Find all ``file://`` urls in the decompiled source

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_file_urlhandler()
        """
        regex = r'\"(file://.+)\"'
        g = self._run_rg(regex=regex, code=show_code, group="-r '$1'")
        match = self._process_match(g, is_url=True)
        self._other_analysis['file_handler'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_content_urlhandler(self, show_code=False) -> GreppedOut:
        """
        Find all ``content://`` urls in the decompiled source

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_content_urlhandler()
        """
        regex = r'\"(content://.+)\"'
        g = self._run_rg(regex=regex, code=show_code, group="-r '$1'")
        match = self._process_match(g, is_url=True)
        self._other_analysis['content_uri'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_websocket_urlhandler(self, show_code=False) -> GreppedOut:
        """
        Find all ``ws://`` or ``wss://`` urls in the decompiled source

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_websocket_urlhandler()
        """
        regex = r'\"(ws://.+|wss://.+)\"'
        g = self._run_rg(regex=regex, code=show_code, group="-r '$1'")
        match = self._process_match(g, is_url=True)
        self._other_analysis['websocket'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_secret_keys(self, show_code=False) -> GreppedOut:
        """
        Find all urls in the decompiled source

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_secret_keys()
        """
        regex = r'(-----(\bBEGIN\b|\bEND\b) ((\bRSA PRIVATE KEY\b)|(\bCERTIFICATE\b)|(\bOPENSSH PRIVATE KEY\b)|(\bDSA PRIVATE KEY\b)|(\bEC PRIVATE KEY\b)|(\bPGP PRIVATE KEY BLOCK\b))-----)'
        g = self._run_rg(regex=regex, code=show_code)
        match = self._process_match(g)
        self._other_analysis['secret_keys'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_aws_keys(self, show_code=False) -> GreppedOut:
        """
        Find all AWS keys in the decompiled source

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_aws_keys()
        """
        regex = r'AKIA[0-9A-Z]{16}'
        g = self._run_rg(regex=regex, code=show_code)
        match = self._process_match(g)
        self._other_analysis['aws_keys'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_github_token(self, show_code=False) -> GreppedOut:
        """
        Find all Github tokens in the decompiled source

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_github_token()
        """
        regex = r"[g|G][i|I][t|T][h|H][u|U][b|B].*[['|\"]0-9a-zA-Z]{35,40}['|\"]"
        g = self._run_rg(regex=regex, code=show_code)
        match = self._process_match(g)
        self._other_analysis['github_token'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_password_in_url(self, show_code=False) -> GreppedOut:
        """
        Find all passwords in urls. Usually used for basic authentication

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_password_in_url()
        """
        regex = r'(\w+://\w+:)(.+)@\w+\.?[\w|\.].*'
        g = self._run_rg(regex=regex, code=show_code)
        match = self._process_match(g)
        self._other_analysis['password_in_url'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_google_ads_import(self, show_code=False) -> GreppedOut:
        """
        Find imports relevant to Google ads

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_google_ads_import()
        """
        regex = r'^import com.google.android.gms.ads'
        g = self._run_rg(regex=regex, code=show_code)
        match = self._process_match(g)
        self._other_analysis['goole_ads_import'] = match
        self.log_debug('')
        return GreppedOut(match)

    @_logger
    def other_find_trackers_ads(self) -> list:
        """
        Find trackers included in the app. Currently it looks for 
        135 trackers.

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        list
            List of matched trackers

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_find_trackers_ads()
        """
        match = []
        if self.__class__.__name__ == 'GlorifiedAndroid':
            path = f'{self._output_dir}/resources'
        else:
            path = self._java_sources
        for k, v in self._TRACKERS.items():
            g = self._run_rg(regex=v, rg_options='-l', path=path)
            if len(g) > 0:
                match.append(k)
        self._other_analysis['trackers'] = match
        self.log_debug('')
        return match

    @_logger
    def other_ad_networks(self, show_code=False) -> GreppedOut:
        """
        Show imports of the popular android ad networks. 
        | `Reference <https://github.com/lioulei1317/Android-Demo/blob/master/javaapk.com-360Satety/src/com/anjoyo/anjoyosafety/util/AdManagerUtil.java>`__
        | `Reference <https://www.appbrain.com/stats/libraries/ad-networks>`__

        Parameters
        ----------
        show_code : bool, optional
            Show the full matched line, by default False
        
        Returns
        -------
        GreppedOut
            GreppedOut object

        Examples
        --------
        >>> from glorifiedgrep import GlorifiedAndroid
        >>> a = GlorifiedAndroid('/path/to/apk')
        >>> a.other_ad_networks()
        """
        match = {}
        if self.__class__.__name__ == 'GlorifiedAndroid':
            path = f'{self._output_dir}/sources'
        else:
            path = self._java_sources
        for k, v in self._AD_NETWORKS.items():
            g = self._run_rg(regex=v, rg_options='-l', path=path)
            if len(g) > 0:
                match[k.lower().replace(' ', '_')] = g
        self._other_analysis['trackers'] = match
        self.log_debug('')
        match['found'] = list(match.keys())
        return GreppedOut(match)
