"""
The backbone doesn't have a relational database or other backend state provider 
It just saves its configuration to the local filesystem
In docker data is saved to a mounted volume for persistence

POSTS to /client create entries in clients.json. The return from the post 
contains a generated secret but subsequent calls to GET /client or 
GET /client/{id} do not return the secret.

Each time .find is called the .get method is called which checks the 
mtime of the file and reloads it if newer. This means that new clients 
should be returned
"""
import json
import logging
import os
import random
import string


class ClientModel:
    file = "./data/clients.json"
    mtime = 0
    clients = {}
    parser = None

    def __init__(self):
        self.get()

    def get(self):
        try:
            mtime = os.path.getmtime(self.file)
            if mtime > self.mtime:
                with open(self.file, "r") as client_file:
                    self.clients = json.load(client_file)
                    self.mtime = mtime
        except FileNotFoundError:
            logging.debug("First time initialisation with empty client list")
            os.makedirs("data", exist_ok=True)
            self.clients = {}
            self.save()
            self.mtime = os.path.getmtime(self.file)

        return self.clients

    def find(self, client_id):
        self.get()
        if client_id in self.clients:
            client = self.clients[client_id]
        else:
            client = None
        return client

    def add(self, client):
        client["secret"] = self.secret()
        self.clients[client["client_id"]] = client
        self.save()
        return client

    def remove(self, client):
        del self.clients[client["client_id"]]
        self.save()

    def update(self, client_updates):
        client = self.find(client_updates["client_id"])
        client.update(client_updates)
        self.clients[client["client_id"]] = client
        self.save()
        return client

    def save(self):
        try:
            with open(self.file, "w") as client_file:
                client_file.write(json.dumps(self.clients, indent=2))
                return True
        except OSError as error:
            print(str(error))
            return False

    def secret(self, chars=36):
        res = "".join(
            random.choices(
                string.ascii_lowercase + string.ascii_uppercase + string.digits, k=chars
            )
        )
        return str(res)