from planner.file_system import FileSystem
from planner.internet_access import *
from planner.specs import *
import time, os

class Sandbox:

    def __init__(self, logging=False):
        self.logging = logging
        return

    def _normalize(self, values):
        # Count number of strong VM indicators (scores of 0)
        vm_indicators = values.count(0)
        
        # If we have any definitive VM indicators (score of 0), 
        # this is almost certainly a VM/sandbox
        if vm_indicators > 0:
            return 0  # 100% certainty
            
        # For remaining checks, use weighted average
        total_weight = 0
        weighted_sum = 0
        
        for value in values:
            # VM-specific checks get higher weight
            if value == 5:
                weight = 2.0
            # Hardware/spec checks get medium weight
            elif value >= 3:
                weight = 1.5
            # Suspicious but not certain checks get lower weight
            else:
                weight = 1.0
                
            weighted_sum += value * weight
            total_weight += weight
        
        score = weighted_sum / total_weight
        
        # Apply penalties for suspicious indicators
        suspicious_count = sum(1 for x in values if x <= 2)
        if suspicious_count >= 3:
            score = max(0, score - 2)  # Major penalty
        elif suspicious_count >= 2:
            score = max(1, score - 1)  # Moderate penalty
        elif suspicious_count == 1:
            score = max(2, score - 0.5)  # Minor penalty
            
        return score


    def is_sandboxed(self):
        s1 = self._check_specs()
        # s2 = self._check_file_system()

        # final_score = self._normalize([s1, s2])
        final_score = s1

        percentage = int(100 - ((final_score / 5) * 100))

        if self.logging:
            self._printout(10, f"Conclusion: {percentage}% chance of being in a virtual environment.\n")

        return percentage / 100

    def _check_file_system(self):
        try:
            if self.logging:
                self._printout(10, "FILESYSTEM")

            # VM-specific checks
            s1, d1, e1 = FileSystem.check_vm_registry_keys()
            s2, d2, e2 = FileSystem.check_vm_files()
            s3, d3, e3 = FileSystem.check_vm_processes()
            s4, d4, e4 = FileSystem.check_prev_logins()

            if self.logging:
                self._printout(score=s1, description=d1, extra=e1)
                self._printout(s2, d2, e2)
                self._printout(s3, d3, e3)
                self._printout(s4, d4, e4)

            # Use weighted average of all checks
            # return self._normalize([s1, s2, s3, s4])
            return self._normalize([s3, s4])
            
        except Exception as e:
            if self.logging:
                self._printout(5, "FILESYSTEM checks partially skipped due to access restrictions.")
            return 5  # Give benefit of doubt on errors


    def _check_specs(self):
        if self.logging:
            self._printout(10, "SPECS OF THE SYSTEM")

        s1, d1, e1 = Specs.check_hard_drive()
        s2, d2, e2 = Specs.check_ram_space()
        s3, d3, e3 = Specs.check_cpu_cores()

        # s4, d4, e4 = Specs.check_serial_number()
        s5, d5, e5 = Specs.check_model()
        s6, d6, e6 = Specs.check_manufacturer()

        # if self.logging:
        #     self._printout(score=s1, description=d1, extra=e1)
        #     self._printout(s2, d2, e2)
        #     self._printout(s3, d3, e3)

        #     self._printout(s4, d4, e4)
        #     self._printout(s5, d5, e5)
        #     self._printout(s6, d6, e6)

        # return self._normalize([s1, s2, s3, s4, s5, s6])
        return self._normalize([s5, s6])

    def _printout(self, score, description, extra=None):

        # enable color in cmd for Windows
        if os.name == 'nt':
            os.system('color')

        _CLEAR = '\033[0m'
        _BOLD = '\033[1m'

        _RED = '\033[91m'
        _ORANGE = '\033[33m'
        _LIME = '\033[92m'


        _ITALIC = '\033[3m'
        _UNDERLINED = '\033[4m'
        _YELLOW =  '\033[93m'

        # 10 is for headers of sections
        if score == 10:
            import shutil
            width = shutil.get_terminal_size((80, 20)).columns
            spaces = (width - len(description))
            if spaces % 2 == 0:
                left_spaces = int(spaces / 2)
                right_spaces = int(left_spaces)
            else:
                left_spaces = int((spaces-1) / 2)
                right_spaces = int(left_spaces + 1)

            left = f'{_BOLD}{_ITALIC}{_UNDERLINED}{_YELLOW}' + left_spaces * ' '
            right = right_spaces * ' ' + f'{_CLEAR}'
            description = f'{left}{description}{right}'

        if score == 5:
            description = f'{_BOLD}{_LIME}[+++++] {description}{_CLEAR}'
        elif score == 4:
            description = f'{_BOLD}{_LIME}[++++-] {description}{_CLEAR}'
        elif score == 3:
            description = f'{_BOLD}{_ORANGE}[+++--] {description}{_CLEAR}'
        elif score == 2:
            description = f'{_BOLD}{_ORANGE}[++---] {description}{_CLEAR}'
        elif score == 1:
            description = f'{_BOLD}{_RED}[+----] {description}{_CLEAR}'
        elif score == 0:
            description = f'{_BOLD}{_RED}[-----] {description}{_CLEAR}'

        # make it a bit more exciting
        print()
        print(description)
        time.sleep(0.2)
        if extra:
            print(f"-> {extra}")
            time.sleep(1)
        time.sleep(1.5)
