# Copyright (C) 2020  Braiins Systems s.r.o.
#
# This file is part of Braiins Open-Source Initiative (BOSI).
#
# BOSI is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
# Please, keep in mind that we may also license BOSI or any part thereof
# under a proprietary license. For more information on the terms and conditions
# of such proprietary license or if you have any other questions, please
# contact us at opensource@braiins.com.

import os
import sys

from typing import Optional, AnyStr

PAYLOAD_DIR = 'payload'


def is_frozen():
    return getattr(sys, 'frozen', False)


def _get_data_root_path():
    """
    Provides the true root path for all files referenced in the code. The
    Tools bundled into a standalone executable by pyinstaller have the necessary local
    files built into the binary. These will be extracted upon startup of the binary.
    See: https://pyinstaller.readthedocs.io/en/stable/spec-files.html#adding-files-to-the-bundle
    :return: empty string if we are not running from a bundle
    """
    if is_frozen():
        return sys._MEIPASS
    else:
        return ''


def get_payload_path(*path):
    return os.path.join(_get_data_root_path(), PAYLOAD_DIR, *path)


def get_program_name(referral_id_from_dir: bool) -> Optional[AnyStr]:
    exec_name = ''
    if referral_id_from_dir:
        exec_name = os.path.basename(
            os.path.normpath(os.path.abspath(os.path.join(sys.argv[0], '../../')))
        )
    else:
        exec_name = os.path.basename(sys.argv[0])
    return os.path.splitext(exec_name)[0] or None


def get_refid(referral_id_from_dir: bool) -> Optional[str]:
    program_name = get_program_name(referral_id_from_dir)
    if not program_name:
        return None
    exploded = program_name.split('_', maxsplit=1)
    return len(exploded) > 1 and exploded[1] or None


def is_valid_hostname(hostname):
    import re

    if len(hostname) > 255:
        return False
    if hostname[-1] == '.':
        hostname = hostname[:-1]  # strip exactly one dot from the right, if present
    allowed = re.compile('(?!-)[A-Z\d-]{1,63}(?<!-)$', re.IGNORECASE)
    return all(allowed.match(x) for x in hostname.split('.'))
