###############################################################################
#
# Copyright (C) 2019 Tom Kralidis
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################

import logging

import redis

from geomet_data_registry import __version__
from geomet_data_registry.store.base import BaseStore, StoreError

LOGGER = logging.getLogger(__name__)


class RedisStore(BaseStore):
    """Redis key-value store implementation"""

    def __init__(self, provider_def):
        """
        Initialize object

        :param provider_def: provider definition dict

        :returns: `geomet_data_registry.store.redis_.RedisStore`
        """

        super().__init__(provider_def)

        try:
            self.redis = redis.Redis.from_url(self.url,
                                              charset='utf-8',
                                              decode_responses=True)
        except redis.exceptions.ConnectionError as err:
            msg = 'Cannot connect to Redis {}: {}'.format(self.url, err)
            LOGGER.exception(msg)
            raise StoreError(msg)

    def setup(self):
        """
        Create the store

        :returns: `bool` of process status
        """

        return self.redis.set('geomet-data-registry-version', __version__)

    def teardown(self):
        """
        Delete the store

        :returns: `bool` of process status
        """

        LOGGER.debug('Deleting all Redis keys')
        keys = [
            key for key in self.redis.scan_iter()
            if key.startswith('geomet-data-registry')
        ]
        for key in keys:
            LOGGER.debug('Deleting key {}'.format(key))
            self.redis.delete(key)

        return True

    def get_key(self, key, raw=False):
        """
        Get key from store

        :param key: key to fetch
        :param raw: `bool` indication whether to add prefix when fetching key

        :returns: `str` of key value from Redis store
        """

        if raw:
            return self.redis.get(key)

        return self.redis.get('geomet-data-registry_{}'.format(key))

    def set_key(self, key, value, raw=False):
        """
        Set key value from

        :param key: key to set value
        :param value: value to set
        :param raw: `bool` indication whether to add prefix when setting key

        :returns: `bool` of set success
        """

        if raw:
            return self.redis.set(key, value)

        return self.redis.set('geomet-data-registry_{}'.format(key), value)

    def list_keys(self, pattern=None):
        """
        List all store keys

        :param pattern: regular expression to filter keys on

        :returns: `list` of all store keys
        """

        if pattern is not None:
            return self.redis.keys(pattern=pattern)

        return self.redis.keys()

    def __repr__(self):
        return '<BaseStore> {}'.format(self.type)
