from abc import ABC, abstractmethod
import json
import os
from typing import Dict, List, Any
from enum import Enum

class Language(Enum):
    PYTHON = "python"
    JAVASCRIPT = "javascript"
    JAVA = "java"
    GO = "go"
    SWIFT = "swift"

class Code:
    def __init__(self, code_snippet: str, language: Language):
        self.code_snippet = code_snippet.strip()
        self.language = language

    def get_lines(self) -> List[str]:
        return self.code_snippet.split('\n')
    
class BaseInstruction(ABC):
    _judge_client = None  # Class variable to store the singleton judge client
    
    @classmethod
    def set_judge_client(cls, judge_client):
        """Set the singleton judge client for all instruction instances"""
        cls._judge_client = judge_client
    
    @classmethod
    def get_judge_client(cls):
        """Get the singleton judge client"""
        if cls._judge_client is None:
            raise ValueError("Judge client has not been initialized. Call BaseInstruction.set_judge_client() first.")
        return cls._judge_client
    
    def __init__(self,
                 instruction_id: str,
                 description: str,
                 config: Dict[str, Any],
                 tags: List[str],
                 supported_languages: List[Language] = None):
        self.instruction_id = instruction_id
        self.description = description
        self.config = config
        self.tags = tags
        self.supported_languages = supported_languages
    
    @property
    def judge_client(self):
        """Property to access the singleton judge client"""
        return self.get_judge_client()
    
    def is_language_supported(self, language: Language) -> bool:
        return language in self.supported_languages    
    
    @abstractmethod
    def check_applicability(self, code: Code) -> bool:
        """Check if this instruction is applicable to the given code"""
        pass

    @abstractmethod
    def verify_application(self, before: Code, after: Code) -> tuple[str, str]:
        """Verify if the instruction was correctly applied"""
        pass
    
        