# -*- 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.


from xivo_dao.helpers.db_manager import Session

from xivo_confd import sysconfd, bus
from xivo_confd.authentication.confd_auth import required_acl
from xivo_confd.database import user_export as user_export_db
from xivo_confd.helpers.restful import ConfdResource
from xivo_confd.plugins.user_import import csvparse
from xivo_confd.plugins.user_import.service import ImportService
from xivo_confd.representations.csv_ import output_csv

EXPORT_COLUMNS = ('uuid',
                  'entity_id',
                  'firstname',
                  'lastname',
                  'email',
                  'mobile_phone_number',
                  'outgoing_caller_id',
                  'language',
                  'call_permission_password',
                  'enabled',
                  'ring_seconds',
                  'simultaneous_calls',
                  'supervision_enabled',
                  'call_transfer_enabled',
                  'call_record_enabled',
                  'online_call_record_enabled',
                  'userfield',
                  'username',
                  'password',
                  'cti_profile_name',
                  'cti_profile_enabled',
                  'voicemail_name',
                  'voicemail_number',
                  'voicemail_context',
                  'voicemail_password',
                  'voicemail_email',
                  'voicemail_attach_audio',
                  'voicemail_delete_messages',
                  'voicemail_ask_password',
                  'line_protocol',
                  'line_site',
                  'provisioning_code',
                  'context',
                  'sip_username',
                  'sip_secret',
                  'sip_options',
                  'exten',
                  'incall_exten',
                  'incall_context',
                  'call_permissions',
                  'labels')


class UserImportResource(ConfdResource):

    def __init__(self, service: ImportService):
        self.service = service

    @required_acl('confd.users.import.create')
    def post(self):
        parser: csvparse.CsvParser = csvparse.parse()
        entries, errors, warnings = self.service.import_rows(parser)

        if errors:
            status_code = 400
            response = {'errors': errors}
            self.rollback()
        else:
            status_code = 201
            response = {'created': [entry.extract_ids() for entry in entries],
                        'warnings': warnings}

        return response, status_code

    @required_acl('confd.users.import.update')
    def put(self):
        parser = csvparse.parse()
        entries, errors, warnings = self.service.update_rows(parser)

        if errors:
            status_code = 400
            response = {'errors': errors}
            self.rollback()
        else:
            status_code = 201
            response = {'updated': [entry.extract_ids() for entry in entries],
                        'warnings': warnings}

        return response, status_code

    def rollback(self):
        Session.rollback()
        sysconfd.rollback()
        bus.rollback()


class UserExportResource(ConfdResource):
    representations = {'text/csv; charset=utf-8': output_csv}

    @required_acl('confd.users.export.read')
    def get(self):
        users_from_db = user_export_db.export_query()
        return {
            'headers': [x for x in EXPORT_COLUMNS],
            'content': list(self._associate_db_query_with_csv_header(EXPORT_COLUMNS, users_from_db))
        }

    def _associate_db_query_with_csv_header(self, csv_header, users_from_db):
        for user_row in users_from_db:
            user = self._clean_user_row(user_row)
            user_with_csv_header = dict(zip(csv_header, user))
            user_dict = self._adapt_db_value_to_csv_column(user_with_csv_header)

            yield user_dict

    def _clean_user_row(self, user):
        return tuple((field or "") for field in user)

    # Helper function to adapt some db content
    # to the expected csv content
    def _adapt_db_value_to_csv_column(self, user):
        return self._extract_from_sip_options(user)

    def _extract_from_sip_options(self, user):
        # The webrtc 'key' contains in fact the usersip.options column content
        # which is the list of the user's SIP options
        sip_options = []
        if user.get('sip_options'):
            for key, value in user.get('sip_options'):
                # WebRTC option is stored as a SIP option
                if key == 'webrtc':
                    if value == 'yes':
                        user['line_protocol'] = 'webrtc'
                    elif value == 'ua':
                        user['line_protocol'] = 'ua'
                else:
                    sip_options.append((key, value))
            
            user['sip_options'] = ';'.join(f'{k}={v}' for k, v in sip_options)
        else:
            user['sip_options'] = ''

        return user
