from abc import ABC, abstractmethod

class Movimento (ABC) :
    def __init__(self, id_sim:str, tempo:int) -> None:
        self._id_sim=id_sim
        self._tempo=tempo

    @property
    def id_sim (self) -> str:
        return self._id_sim
    
    @property
    def tempo (self) -> int:
        return self._tempo
    
    @abstractmethod
    def get_importo(self) -> float:
        pass

class Chiamata (Movimento):
    def __init__(self, id_sim: str, tempo: int, \
                 id_sim_destinatario:str, durata:int) -> None:
        super().__init__(id_sim, tempo)
        self._id_sim_destinatario = id_sim_destinatario
        self._durata = durata
    
    def get_importo(self) -> float:
        return - 0.20 - 0.005 * self._durata
    
class Sms (Movimento):
    def __init__(self, id_sim: str, tempo: int, \
                 id_sim_destinatario:str) -> None:
        super().__init__(id_sim, tempo)
        self._id_sim_destinatario = id_sim_destinatario
    
    @property
    def id_sim_destinatario (self) -> str:
        return self._id_sim_destinatario
    
    def get_importo(self) -> float:
        return - 0.15
    
class Ricarica (Movimento):
    def __init__(self, id_sim: str, tempo: int, \
                 importo:float) -> None:
        super().__init__(id_sim, tempo)
        if (importo < 0.01): 
            raise Exception("Importo non valide")
        self._importo=importo
    
    def get_importo(self) -> float:
        return self._importo


class Gestore:
    _movimenti:list[Movimento] = []

    def get_sms_tra_due (self, id_sim_1: str, \
                         id_sim_2: str, tempo_inizio:int,\
                         tempo_fine:int) -> int:
        conto:int =0
        for m in self._movimenti:
            if isinstance(m, Sms) and  \
                tempo_inizio <= m.tempo <= tempo_fine and \
                (
                    (m.id_sim == id_sim_1 and m.id_sim_destinatario == id_sim_2)
                or 
                 (m.id_sim == id_sim_2 and m.id_sim_destinatario == id_sim_1)
                ):
                conto += 1
        return conto
