# -*- coding: utf-8 -*-
#
# Copyright (C) 2015-2016 Avencall
#
# 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 os
from contextlib import contextmanager

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from xivo_dao.resources.utils.searchers import SearchConfig

from xivo_dird import BaseSourcePlugin
from xivo_dird import make_result_class
from xivo_dird.dao import meetingroom

logger = logging.getLogger(__name__)


class MeetingroomBackend(BaseSourcePlugin):
    # keyword in config 'meetingroom.yml' allowing to set words which causes search for all meeting rooms
    GET_ALL_ROOMS_CONFIG_KEY = 'get_all_rooms_keywords'

    def load(self, config, search_engine=None):
        logger.debug(
            'Loading meeting room source. %s',
            'Search engine was supplied.' if search_engine else 'Search engine will be created.'
        )

        unique_column = 'id'
        source_name = config['config']['name']
        format_columns = config['config'].get(self.FORMAT_COLUMNS, {})

        self.room_result = make_result_class(
            source_name,
            unique_column,
            format_columns,
        )
        self.session = scoped_session(sessionmaker())
        if search_engine:
            self._search_engine = search_engine
        else:
            self.session.configure(bind=create_engine(config['config']['db_uri']))
            self._search_engine = search_engine or meetingroom.MeetingroomSearchSystem(
                SearchConfig(**meetingroom.get_configuration()))

        self.searched_columns = config['config'][self.SEARCHED_COLUMNS]
        self.first_match_column = config['config'].get(self.FIRST_MATCHED_COLUMNS)
        self.xivo_uuid = os.getenv('XIVO_UUID')
        self.magic_words_to_get_all_rooms = list(
            map(str.strip, config['config'].get(self.GET_ALL_ROOMS_CONFIG_KEY, '').split(','))
        )

    @contextmanager
    def _new_session(self):
        session = self.session()
        try:
            yield session
        finally:
            session.close()

    def _is_magic_keyword(self, keyword):
        return keyword.strip().lower() in self.magic_words_to_get_all_rooms

    def search(self, term, args=None):
        logger.debug('Searching meeting room with - %s, %s', term, args)
        term = '' if self._is_magic_keyword(term) else term
        user_uuid = args.get('xivo_user_uuid')
        params = {
            'search': term,
            'user_uuid': user_uuid,
            'searched_columns': self.searched_columns
        }
        with self._new_session() as session:
            rooms = self._search_engine.search(session, params)[0]
        return self.format_rooms(rooms, user_uuid=user_uuid)

    def first_match(self, term, args=None):
        logger.debug('First matching meeting room - %s, %s', term, args)
        if self.first_match_column is None:
            logger.error('Column for reverse lookup is not defined.')
            return dict()

        user_uuid = args.get('xivo_user_uuid')
        params = {
            'user_uuid': user_uuid,
            self.first_match_column: term
        }
        with self._new_session() as session:
            rooms = list(self._search_engine.search(session, params)[0])
        return self.format_room(rooms[0], user_uuid=user_uuid) if rooms else dict()

    def list(self, source_entry_ids, args=None):
        logger.debug('Listing meeting rooms - "%s", "%s"', source_entry_ids, args)
        user_uuid = args.get('token_infos', {}).get('xivo_user_uuid')
        params = {
            'user_uuid': user_uuid,
            'unique_ids': source_entry_ids
        }

        with self._new_session() as session:
            matching_rooms = self._search_engine.search(session, params)[0]
        return self.format_rooms(matching_rooms, user_uuid=user_uuid)

    def format_room(self, room, user_uuid=None):
        room = room._asdict()
        personal = room.pop('room_type')
        room = self.room_result(room, user_uuid=user_uuid, xivo_id=self.xivo_uuid)
        room.is_personal = (personal == meetingroom.PERSONAL)
        return room

    def format_rooms(self, rooms, user_uuid=None):
        return [self.format_room(_, user_uuid=user_uuid) for _ in rooms]
