"""Abstract API classes."""
import json


JSON_RPC_VERSION = '2.0'


class AbstractAPI:
    """Abstract interface of all children APIs.

    This is repsonsible for setting the right attributes
    that ``Request`` uses to build the request dict."""

    def __init__(self):
        with open('params.json') as f:
            self._methods = json.load(f)

    def __getattr__(self, name):
        print('METHODS:', self._methods)
        if name in self._methods:
            return self._make_method(name)
        else:
            msg = '{} is not an available method on the {} API.'
            api_name = self.__class__.__name__
            raise AttributeError(msg.format(name, api_name))

    def _make_method(self, name):
        cls_name = self.__class__.__name__.lower()
        method_name = cls_name + '.' + name

        def method(**kwargs):
            self.params = kwargs
            self.method = method_name
            return self()

        # interactive/debugging
        method.__qualname__ = method_name

        setattr(self, name, method)

        return method


class Request:
    """Object representing the request dict.

    This does not provide any API related functionality,
    it must be used together with ``AbstractAPI``."""

    jsonrpc = JSON_RPC_VERSION
    method = None
    params = None
    id = 0
    auth = None

    def __new__(cls, *args, **kwargs):
        req = super().__new__(cls)
        # each request has a unique id
        req.id = Request.id = Request.id + 1
        return req

    def __call__(self):
        return {
            'jsonrpc': self.jsonrpc,
            'method': self.method,
            'params': self.params,
            'id': self.id,
            'auth': self.auth}


class API(AbstractAPI, Request):
    """Base class of all Zabbix APIs."""
