import requests


BASE_URL = '{host}/resellers/api/v1/{operation}'


class TunnelManager(object):

    class TerminateAccountError(Exception):
        """Raised when we cannot terminate an account. This need to be
        propagated through the stack so the program using
        terminate_account() can decide what to do.

        """
        pass

    def __init__(self, partner_id, secret, host):

        self.partner_id = partner_id
        self.secret = secret
        self.host = host

    def create_account(self):
        """Creates a new authentication set of credentials. Returns None if
        the request doesn't succeed. Returns a dictionary with the following
        keys if it succeeds:

        username: new username created.
        password: password generated for the user.
        status: This is the account status, should be "active".
        started_at: time at which the account was started.
        paused_at: time at which the account was paused.
        endend_at: time at which the account was endned.
        """
        url = BASE_URL.format(host=self.host, operation='create')
        payload = {'secret': self.secret,
                   'partner_id': self.partner_id}
        r = requests.post(url, data=payload)
        if r.status_code == 200:
            return r.json()
        return None

    def terminate_account(self, username):
        """Terminates an account for the specified username. Returns None if
        the request doesn't succeed. Returns a dictionary with the
        following keys if it succeeds:

        username: username of the terminated account.
        status: Account status after termintation, should be "inactive".
        started_at: time at which the account was started.
        paused_at: time at which the account was paused, should be None.
        endend_at: time at which the account was endned.
        """
        url = BASE_URL.format(host=self.host, operation='terminate')
        payload = {'secret': self.secret,
                   'partner_id': self.partner_id,
                   'username': username}
        r = requests.post(url, data=payload)
        if r.status_code == 200:
            return r.json()
        raise self.TerminateAccountError(
            "Account {} couldn't be terminated.".format(username))

    def find_account(self):
        pass

    def pause_account(self, username):
        """Pauses an account for the specified username, temporarily revoking
        access to the tunnel. Returns None if the request doesn't
        succeed. Returns a dictionary with the following keys if it
        succeeds:

        username: username of the paused account.

        status: Account status after termintation, should be "paused".

        started_at: time,in Unix epoch, at which the account was
                    started.

        paused_at: time, in Unix epoch, at which the account was
                   paused, should be close to now.

        ended_at: time, in Unix epoch at which the account was ended,
                  should be None.
        """
        url = BASE_URL.format(host=self.host, operation='pause')
        payload = {'secret': self.secret,
                   'partner_id': self.partner_id,
                   'username': username}
        r = requests.post(url, data=payload)
        if r.status_code == 200:
            return r.json()
        return None

    def resume_account(self, username):
        """Resumes an account for the specified username, granting access to
        the tunnel. Returns None if the request doesn't
        succeed. Returns a dictionary with the following keys if it
        succeeds:

        username: username of the resumed account.

        status: Account status after termintation, should be "active".

        started_at: time,in Unix epoch, at which the account was
                    started.

        paused_at: time, in Unix epoch, at which the account was
                   paused, should be None.

        ended_at: time, in Unix epoch at which the account was ended,
                  should be None.

        """
        url = BASE_URL.format(host=self.host, operation='resume')
        payload = {'secret': self.secret,
                   'partner_id': self.partner_id,
                   'username': username}
        r = requests.post(url, data=payload)
        if r.status_code == 200:
            return r.json()
        return None

    def update_password(self, username, current_password, new_password):
        """Updates the password for the account specified by username. Returns
        None if the request doesn't succeed. Returns a dictionary with
        the following keys if it succeeds:

        username: username the for which password was changed.

        status: Account status after termintation, should be "active".

        started_at: time,in Unix epoch, at which the account was
                    started. should be None.

        paused_at: time, in Unix epoch, at which the account was
                   paused, should be None.

        ended_at: time, in Unix epoch at which the account was ended,
                  should be None.

        current_password: Old password for the account.

        new_password: New password for the account.

        """
        url = BASE_URL.format(host=self.host, operation='update_password')
        payload = {'secret': self.secret,
                   'partner_id': self.partner_id,
                   'username': username,
                   'current_password': current_password,
                   'new_password': new_password}
        r = requests.post(url, data=payload)
        if r.status_code == 200:
            return r.json()
        return None

    def list_accounts(self):
        pass
