from typing import Callable, Union
from adam.commands import validate_args
from adam.commands.command import Command
from adam.utils_context import Context
from adam.utils_job.job_status import JobStatus
from adam.utils_repl.repl_session import ReplSession
from adam.utils_repl.repl_state import ReplState
from adam.utils_job.job import Job
from adam.utils_job.job_completer import job_completer

class Retry(Command):
    COMMAND = 'retry'

    # if class method exists, injected to member method by repl.py
    run_command: Callable[[str, ReplSession, list[Command], Command, callable, Job, Context], Union[ReplState, JobStatus]] = None

    # the singleton pattern
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, 'instance'): cls.instance = super(Retry, cls).__new__(cls)

        return cls.instance

    def __init__(self, successor: Command=None):
        super().__init__(successor)

    def command(self):
        return Retry.COMMAND

    def aliases(self):
        return [':!']

    def run(self, cmd: str, state: ReplState):
        if not (args := self.args(cmd)):
            return super().run(cmd, state)

        with self.validate(args, state) as (args, state):
            with validate_args(args, state, name='job id') as job_id:
                with self.context(args) as (args, ctx):
                    if ctx.debug:
                        ctx.show_out=True

                    job = Job.job(job_id)
                    if not job:
                        ctx.log2('Job not found.')
                        return state

                    if not job.raw_command:
                        ctx.log2('Cannot find raw command for job.')
                        return state

                    r = self.run_command(state, job.raw_command, job=job)
                    if not r:
                        ctx.log2('Command is not retriable, ignored.')

                    return state

    def completion(self, state: ReplState):
        return super().completion(state, job_completer(retriable=True))

    def help(self, state: ReplState):
        return super().help(state, 'retry command', args='[job_id]')