#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you 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 django.contrib.auth.models import User, Group
from django.shortcuts import get_object_or_404
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from rest_framework import permissions, status, viewsets
from rest_framework.response import Response
from . import serializers
from .. import models


schema_view = get_schema_view(
    openapi.Info(
        title='Bloodhound Core API',
        default_version='v1',
    ),
    public=True,
    permission_classes=(permissions.AllowAny,),
)


class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = serializers.UserSerializer


class GroupViewSet(viewsets.ModelViewSet):
    queryset = Group.objects.all()
    serializer_class = serializers.GroupSerializer


class ProductViewSet(viewsets.ModelViewSet):
    queryset = models.Product.objects.all()
    serializer_class = serializers.ProductSerializer
    lookup_field = 'prefix'


class TicketViewSet(viewsets.ModelViewSet):
    queryset = models.Ticket.objects.all()
    serializer_class = serializers.TicketSerializer
    lookup_field = 'product_ticket_id'

    def get_queryset(self, *args, **kwargs):
        prefix = self.kwargs['product_prefix']
        return models.Ticket.objects.filter(product=prefix)


class ComponentViewSet(viewsets.ModelViewSet):
    queryset = models.Component.objects.all()
    serializer_class = serializers.ComponentSerializer
    lookup_field = 'name'

    def get_queryset(self, *args, **kwargs):
        prefix = self.kwargs['product_prefix']
        return models.Component.objects.filter(product=prefix)


class MilestoneViewSet(viewsets.ModelViewSet):
    queryset = models.Milestone.objects.all()
    serializer_class = serializers.MilestoneSerializer
    lookup_field = 'name'

    def get_queryset(self, *args, **kwargs):
        prefix = self.kwargs['product_prefix']
        return models.Milestone.objects.filter(product=prefix)


class VersionViewSet(viewsets.ModelViewSet):
    queryset = models.Version.objects.all()
    serializer_class = serializers.VersionSerializer
    lookup_field = 'name'

    def get_queryset(self, *args, **kwargs):
        prefix = self.kwargs['product_prefix']
        return models.Version.objects.filter(product=prefix)
