# Copyright (c) 2016 Catalyst IT Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from collections import defaultdict

from django.utils.translation import gettext_lazy as _
from django.utils.translation import ngettext_lazy

from horizon import exceptions
from horizon import tables

from adjutant_ui.api import adjutant


class InviteUser(tables.LinkAction):
    name = "invite"
    verbose_name = _("Invite User")
    url = "horizon:management:project_users:invite"
    classes = ("ajax-modal",)
    icon = "plus"

    @staticmethod
    def action_past(count):
        return ngettext_lazy(
            u"Invited User",
            u"Invited Users",
            count
        )


class ResendInvitation(tables.BatchAction):
    name = "resend"

    @staticmethod
    def action_present(count):
        return ngettext_lazy(
            u"Resend Invitation",
            u"Resend Invitations",
            count
        )

    @staticmethod
    def action_past(count):
        return ngettext_lazy(
            u"Invitation re-sent",
            u"Invitations re-sent",
            count
        )

    def allowed(self, request, user=None):
        # Only invited users can be re-invited
        return user.cohort == 'Invited'

    def action(self, request, datum_id):
        user = self.table.get_object_by_id(datum_id)
        adjutant.user_invitation_resend(request, user.id)


class UpdateUser(tables.LinkAction):
    name = "update"
    verbose_name = _("Update User")
    url = "horizon:management:project_users:update"
    classes = ("ajax-modal",)
    icon = "pencil"

    def allowed(self, request, user=None):
        # Currently, we only support updating existing users
        return user.cohort == 'Member'


class RevokeUser(tables.DeleteAction):
    help_text = _("This will remove the selected user(s) from the current "
                  "project.")

    @staticmethod
    def action_present(count):
        return ngettext_lazy(
            u"Revoke User",
            u"Revoke Users",
            count
        )

    @staticmethod
    def action_past(count):
        return ngettext_lazy(
            u"Revoked User",
            u"Revoked Users",
            count
        )

    def delete(self, request, obj_id):
        user = self.table.get_object_by_id(obj_id)

        # NOTE(dale): There is a different endpoint to revoke an invited user
        #             than an Active user.
        result = None
        if user.cohort == 'Invited':
            # Revoke invite for the user
            result = adjutant.user_revoke(request, user.id)
        else:
            # Revoke all roles from the user.
            # That'll get them out of our project; they keep their account.
            result = adjutant.user_roles_remove(
                request, user.id, user.roles)
        if not result or result.status_code not in [200, 202]:
            exception = exceptions.NotAvailable()
            exception._safe_message = False
            raise exception


class UpdateUserRow(tables.Row):
    ajax = True

    def get_data(self, request, user_id):
        user = adjutant.user_get(request, user_id)
        return user

    def load_cells(self, user=None):
        super(UpdateUserRow, self).load_cells(user)
        user = self.datum
        self.classes.append('category-' + user.cohort)


class CohortFilter(tables.FixedFilterAction):
    def get_fixed_buttons(self):
        def make_dict(text, value, icon):
            return dict(text=text, value=value, icon=icon)

        buttons = []
        buttons.append(make_dict(_('Project Users'),
                                 'Member',
                                 'fa-user-md'))
        buttons.append(make_dict(_('Invited Users'),
                                 'Invited',
                                 'fa-user'))
        return buttons

    def categorize(self, table, users):
        categorized_users = defaultdict(list)
        for u in users:
            categorized_users[u.cohort].append(u)
        return categorized_users


def UserRoleDisplayFilter(role_list):
    roles = [adjutant.get_role_text(r) for r in role_list]
    return ', '.join(roles)


class UsersTable(tables.DataTable):
    uid = tables.Column('id', verbose_name=_('User ID'))
    name = tables.Column('name', verbose_name=_('Name'))
    email = tables.Column('email', verbose_name=_('Email'))
    roles = tables.Column('roles',
                          verbose_name=_('Roles'),
                          filters=[UserRoleDisplayFilter])
    status = tables.Column('status', verbose_name=_('Status'))
    cohort = tables.Column('cohort',
                           verbose_name=_('Member Type'),
                           hidden=True)

    class Meta(object):
        name = 'users'
        row_class = UpdateUserRow
        verbose_name = _('Users')
        columns = ('id', 'name', 'email', 'roles', 'status', 'cohort')
        table_actions = (CohortFilter, InviteUser, RevokeUser)
        row_actions = (UpdateUser, ResendInvitation, RevokeUser)
        multi_select = True
