# -*- coding: utf-8 -*-
import codecs
import concurrent.futures
import copy
import json
import logging
import os

from bthlabs_jsonrpc_core import register_method

LOGGER = logging.getLogger('homehub.lib.state_store')


class StateStore:
    def __init__(self, state_path):
        self.state = {'backend': {}, 'frontend': {}}
        self.state_path = state_path
        self.threadpool = None

    def load_state(self):
        if self.state_path is not None and os.path.isfile(self.state_path):
            with codecs.open(self.state_path, 'r', 'utf-8') as state_f:
                self.state = json.load(state_f)

    async def on_app_startup(self, app):
        LOGGER.debug('Initializing threadpool...')
        self.threadpool = concurrent.futures.ThreadPoolExecutor(max_workers=1)

    async def on_app_cleanup(self, app):
        if self.threadpool is not None:
            LOGGER.debug('Shutting down threadpool...')
            self.threadpool.shutdown()

    def get(self):
        return self.state

    def do_save(self, state):
        if self.state_path is not None:
            with codecs.open(self.state_path, 'w', 'utf-8') as state_f:
                state_f.write(json.dumps(state, indent=2))

    def save(self, state):
        self.state = state
        self.threadpool.submit(self.do_save, state)


@register_method('state.get_frontend')
async def get_frontend_state(request):
    return request.config_dict['STATE'].get()['frontend']


@register_method('state.save_frontend')
async def save_frontend_state(request, new_state):
    state = copy.deepcopy(request.config_dict['STATE'].get())
    state['frontend'] = new_state
    request.config_dict['STATE'].save(state)

    await request.app.notify_subscribers({
        'type': 'STATE_NOTIFICATION',
        'data': new_state,
    })

    return True


def setup(app):
    store = StateStore(app['SETTINGS'].STATE_PATH)
    store.load_state()

    app.on_startup.append(store.on_app_startup)
    app.on_cleanup.append(store.on_app_cleanup)

    app['STATE'] = store
