class UserForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ['username', 'password', 'email'] class TechForm(forms.ModelForm):

    class Meta:
        model = Tech
        fields = ['experience', 'job_title', 'shop'] class LoginForm(forms.Form):
    username = forms.CharField(max_length=40, required=True)
    password = forms.CharField(widget=forms.PasswordInput, required=True)

    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')
        user = authenticate(username=username, password=password)
        if not user or not user.is_active:
            raise forms.ValidationError("Sorry, that login was invalid. Please try again.")
        return self.cleaned_data

    def login(self, request):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')
        user = authenticate(username=username, password=password)
        return user class Vote(models.Model):
    tech = models.ForeignKey(Tech)
    solution = models.ForeignKey(Solution, related_name='votes')
    value = models.IntegerField(default=1) class Problem(models.Model):
    title = models.CharField(max_length=65)
    system = models.ForeignKey(System, related_name='problems')
    description = models.TextField(max_length=500)
    tech = models.ForeignKey(Tech, related_name='problems')
    model = models.ForeignKey(Model)
    posted = models.DateTimeField(auto_now=True) class Solution(models.Model):
    description = models.TextField(max_length=500)
    time_required = models.FloatField(default=0)
    parts_cost = models.DecimalField(max_digits=6, decimal_places=2)
    problem = models.ForeignKey(Problem, related_name='solutions')
    tech = models.ForeignKey(Tech, related_name='solutions')
    posted = models.DateTimeField(auto_now=True)
    score = models.IntegerField(default=0) class Tech(models.Model):
    experience = models.IntegerField(default=0)
    job_title = models.CharField(max_length=25)
    shop = models.CharField(max_length=25)
    user = models.OneToOneField(User)
    tech_rating = models.IntegerField(default=0) class Rating(models.Model):
    tech = models.ForeignKey(Tech)
    value = models.IntegerField(default=5) class System(models.Model):
    name = models.CharField(max_length=25) class Brand(models.Model):
    name = models.CharField(max_length=25)

    def __repr__(self):
        return str(self.name) class Model(models.Model):
    name = models.CharField(max_length=40)
    brand = models.ForeignKey(Brand)
    year = models.IntegerField(default=0)

    def __repr__(self):
        return str(self.name) class Problem_Model(models.Model):
    problem = models.ForeignKey(Problem)
    model = models.ForeignKey(Model) class Notification(models.Model):
    tech = models.ForeignKey(Tech, related_name='techs')
    message = models.CharField(max_length=20)
    # is this the best way to link notifications to events?
    solution = models.ForeignKey(Solution, related_name='solution',null=True)
    commit = models.ForeignKey(Commit, related_name='commit',null=True)
    posted = models.DateTimeField(auto_now=True) class VoteSerializer(serializers.ModelSerializer):

    class Meta:
        model = Vote
        fields = "__all__" class ProblemGetSerializer(serializers.ModelSerializer):
    solutions = SolutionGetSerializer(many=True, read_only=True)
    tech = TechGetSerializer(many=False, read_only=True)
    system = SystemSerializer(many=False, read_only=True)

    class Meta:
        model = Problem
        fields = ['id', 'title', 'system', 'description', 'tech',
                  'model', 'posted', 'url', 'solutions'] class UserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True)

    def create(self, validated_data):
        user = User.objects.create(
            username=validated_data['username'],
            email=validated_data['email']
            )
        user.set_password(validated_data['password'])
        user.save()
        return user

    class Meta:
        model = User
        fields = ['id', 'password', 'email', 'username']
        read_only_fields = ['is_staff', 'is_superuser', 'is_active',
                            'date_joined',] class TechGetSerializer(serializers.ModelSerializer):
    user = UserSerializer(many=False, read_only=True)

    class Meta:
        model = Tech
        fields = ['id', 'experience', 'job_title', 'shop', 'user',
                  'tech_rating'] class RatingSerializer(serializers.ModelSerializer):

    class Meta:
        model = Rating
        fields = "__all__" class SystemSerializer(serializers.ModelSerializer):

    class Meta:
        model = System
        fields = ['id', 'name', 'url'] class BrandSerializer(serializers.ModelSerializer):

    class Meta:
        model = Brand
        fields = ['id', 'name', 'url'] class ModelSerializer(serializers.ModelSerializer):
    brand = BrandSerializer(many=False, read_only=True)

    class Meta:
        model = Model
        fields = ['id', 'name', 'brand', 'year', 'url'] class ProblemPostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Problem
        fields = ['id', 'title', 'system', 'description', 'tech',
                  'model', 'posted', 'url'] class SolutionPostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Solution
        fields = ['id', 'description', 'time_required', 'parts_cost',
                  'problem', 'tech', 'posted', 'score', 'url'] class SolutionGetSerializer(serializers.ModelSerializer):
    votes = VoteSerializer(many=True, read_only=True)
    commits = CommitSerializer(many=True, read_only=True)
    tech = TechGetSerializer(many=False, read_only=True)

    class Meta:
        model = Solution
        fields = ['id', 'description', 'time_required', 'parts_cost',
                  'problem', 'tech', 'posted', 'score', 'commits',
                  'votes', 'url'] class TechPostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Tech
        fields = ['id', 'experience', 'job_title', 'shop', 'user',
                  'tech_rating'] class NotificationSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = Notification
        fields = ['id', 'tech', 'message', 'posted', 'solution', 'commit']
from django.shortcuts import render, HttpResponse, HttpResponseRedirect
from rest_framework import permissions
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework import viewsets, permissions, generics, filters
from . import models, forms
from .forms import UserForm, TechForm, LoginForm
from .models import Vote, Problem, Solution, Tech, Rating, System, Brand
from .models import Model, Problem_Model, Notification
from .serializers import VoteSerializer, ProblemGetSerializer, UserSerializer
from .serializers import TechGetSerializer, RatingSerializer, SystemSerializer
from .serializers import BrandSerializer, ModelSerializer, ProblemPostSerializer
from .serializers import SolutionPostSerializer, SolutionGetSerializer
from .serializers import TechPostSerializer, NotificationSerializer
from django.views.generic import ListView
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.decorators import login_required
from django_filters.rest_framework import DjangoFilterBackend
from django.contrib.auth.models import User
from .permissions import IsStaffOrTargetUser
import django_filters

@login_required(login_url='/login/')
def problem_list(request, model, id):
    return render(request, 'problem_list.html')


@login_required(login_url='/login/')
def model_detail(request, id):
    return render(request, 'bike_detail.html')


@login_required(login_url='/login/')
def problem_detail(request, id):
    return render(request, 'problem_detail.html')


@login_required(login_url='/login/')
def profile(request):
    return render(request, 'profile.html')


# class viewsets and filters
class UserView(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    model = User

    def get_permissions(self):
        return (AllowAny() if self.request.method == 'POST'
                else IsStaffOrTargetUser()),


class SystemViewSet(viewsets.ModelViewSet):
    queryset = System.objects.all()
    serializer_class = SystemSerializer
    permission_classes = (permissions.IsAuthenticated,)


class ModelFilter(django_filters.rest_framework.FilterSet):

    class Meta:
        model = Model
        fields = ['brand', 'year']


class ModelViewSet(viewsets.ModelViewSet):
    queryset = Model.objects.all().order_by('name')
    serializer_class = ModelSerializer
    filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
    filter_class = ModelFilter
    permission_classes = (permissions.IsAuthenticated,)


class BrandViewSet(viewsets.ModelViewSet):
    queryset = Brand.objects.all().order_by('name')
    serializer_class = BrandSerializer
    permission_classes = (permissions.IsAuthenticated,)


class ProblemFilter(django_filters.rest_framework.FilterSet):
    no_solutions = django_filters.BooleanFilter(name='solutions',
                                                lookup_expr='isnull')

    class Meta:
        model = Problem
        fields = ['system', 'model', 'tech', 'no_solutions']


class ProblemGetViewSet(viewsets.ModelViewSet):
    queryset = Problem.objects.all().order_by('-posted')
    serializer_class = ProblemGetSerializer
    filter_backends = (django_filters.rest_framework.DjangoFilterBackend,filters.SearchFilter,)
    filter_class = ProblemFilter
    search_fields = ['title']
    permission_classes = (permissions.IsAuthenticated,)


class ProblemPostViewSet(viewsets.ModelViewSet):
    queryset = Problem.objects.all()
    serializer_class = ProblemPostSerializer
    filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
    filter_class = ProblemFilter
    permission_classes = (permissions.IsAuthenticated,)


class SolutionGetViewSet(viewsets.ModelViewSet):
    queryset = Solution.objects.all()
    serializer_class = SolutionGetSerializer
    permission_classes = (permissions.IsAuthenticated,)


class SolutionPostViewSet(viewsets.ModelViewSet):
    queryset = Solution.objects.all()
    serializer_class = SolutionPostSerializer
    permission_classes = (permissions.IsAuthenticated,)


class VoteFilter(django_filters.rest_framework.FilterSet):

    class Meta:
        model = Vote
        fields = ['solution', 'tech']


class VoteViewSet(viewsets.ModelViewSet):
    queryset = Vote.objects.all()
    serializer_class = VoteSerializer
    filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
    filter_class = VoteFilter
    permission_classes = (permissions.IsAuthenticated,)


class TechGetViewSet(viewsets.ModelViewSet):
    queryset = Tech.objects.all()
    serializer_class = TechGetSerializer
    permission_classes = (permissions.IsAuthenticated,)


class TechPostViewSet(viewsets.ModelViewSet):
    queryset = Tech.objects.all()

    serializer_class = TechPostSerializer