from .grpc.core_pb2 import (
    AddItemRequest,
    BasketApplyDiscountRequest,
    BasketAssignOwnerRequest,
    BasketRequest,
    BasketRetrieveRequest,
    EndTradeRequest,
    InstallmentTermRequest,
    RemoveItemRequest,
    StartTradeRequest,
)
from .grpc.core_pb2_grpc import (
    BasketControllerStub,
    InstallmentTermControllerStub,
    TradeControllerStub,
)

SUCCESS_CODE = "0"


def _singletonize_class_vars(cls):
    for attr_name, attr_value in cls.__dict__.items():
        if isinstance(attr_value, type):  # it's a class
            orig_cls = attr_value

            class SingletonWrapper(orig_cls):
                _instances = {}

                def __new__(cls, *args, **kwargs):
                    if cls not in cls._instances:
                        cls._instances[cls] = super().__new__(cls)
                    return cls._instances[cls]

            setattr(cls, attr_name, SingletonWrapper)
    return cls


class BasketRequestMessages:
    RETRIEVE = BasketRetrieveRequest
    CREATE = BasketRequest
    ADD_ITEM = AddItemRequest
    REMOVE_ITEM = RemoveItemRequest
    ASSIGN_OWNER = BasketAssignOwnerRequest
    APPLY_DISCOUNT = BasketApplyDiscountRequest


class BasketRPCMethodNames:
    RETRIEVE = "Retrieve"
    CREATE = "Create"
    ADD_ITEM = "AddItem"
    REMOVE_ITEM = "RemoveItem"
    ASSIGN_OWNER = "AssignOwner"
    APPLY_DISCOUNT = "ApplyDiscount"


class TradeRequestMessages:
    START = StartTradeRequest
    END = EndTradeRequest


class TradeRPCMethodNames:
    START = "Start"
    END = "End"


class InstallmentTermRequestMessages:
    RETRIEVE = InstallmentTermRequest


class InstallmentTermRPCMethodNames:
    RETRIEVE = "Retrieve"


@_singletonize_class_vars
class Stubs:
    BASKET = BasketControllerStub
    TRADE = TradeControllerStub
    INSTALLMENT_TERM = InstallmentTermControllerStub
