from django.conf import settings
from django.contrib.auth import authenticate, get_user_model, login, logout
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.http import HttpResponseNotFound, HttpResponse
from django.shortcuts import redirect
from django.views.generic.base import View, TemplateResponseMixin
from hashcut.models import Mashup, Branding
from ldt.api.ldt.resources import ProjectResource
from ldt.ldt_utils.models import Project, Content
from ldt.security.cache import cached_assign
import re

User = get_user_model()

class MashupContextView(View):
    
    branding = "iri"
    
    def get_context_dict(self, request):
        context = {}
        context["branding"] = self.branding
        context["nb_mashup_creator"] = "0"
        context["top_header_partial"] = "partial/%s_top_header.html"%self.branding
        if request and request.user and isinstance(request.user, User):
            if not self.branding or self.branding=="":
                self.branding = "iri"
            brd = Branding.objects.get(name=self.branding)
            context["nb_mashup_creator"] = Mashup.objects.filter(branding=brd,project__owner=request.user).count()
        return context
            

class MashupHome(TemplateResponseMixin, MashupContextView):
    
    def get_template_names(self):
        return "mashup_home.html"
    
    def get(self, request, branding="iri", **kwargs):
        self.branding = branding
        brd = Branding.objects.get(name=self.branding)
        m1 = None
        m2 = None
        last_mashups = None
        mashups = Mashup.objects.filter(branding=brd).order_by('-project__creation_date')[:6]
        l = len(mashups)
        if l>0:
            m1 = mashups[0]
        if l>1:
            m2 = mashups[1]
        if l>2:
            last_mashups = mashups[2:]
        
        contents = Content.objects.filter(tags__icontains=branding).order_by('?')[:4]
        
        context = self.get_context_dict(request)
        context.update({"mashups":last_mashups, "contents": contents, "m1":m1, "m2":m2})
        return self.render_to_response(context)
    


class MashupEdit(TemplateResponseMixin, MashupContextView):
    
    def get_template_names(self):
        return "mashup_edit.html"
    
    def get(self, request, branding="iri", **kwargs):
        self.branding = branding
        context = self.get_context_dict(request)
        return self.render_to_response(context)



# save mashup view, not include in generic views
def save_mashup(request, branding="iri"):
    # First we use the project api to save the project
    proj_api = ProjectResource()
    rtrn = proj_api.dispatch_list(request)
    if rtrn and rtrn['Location']:
        # The api return the api location of the created project (i.e. /a/b/ldt_id/). So we just get the id to get the project object.
        proj_ldt_id = rtrn['Location'].split("/")[-2]
        try:
            proj = Project.objects.get(ldt_id=proj_ldt_id)
        except Project.DoesNotExist:
            raise ObjectDoesNotExist("Save Mashup : project not found. project_ldt_id = " + proj_ldt_id)
        # Now that we have the project object, we can save the mashup object
        brd = Branding.objects.get(name=branding)
        new_mashup = Mashup()
        new_mashup.branding = brd
        new_mashup.project = proj
        new_mashup.save()
        # We assign permission for the group associated to branding
        grp = brd.group
        if grp:
            cached_assign('view_project', grp, proj)
            if request.user and isinstance(request.user, User):
                request.user.groups.add(grp)
    return rtrn
    


class MashupHashcut(TemplateResponseMixin, MashupContextView):
    
    def get_template_names(self):
        return "mashup_hashcut.html"
    
    def get(self, request, branding="iri", ldt_id=None, **kwargs):
        self.branding = branding
        if not ldt_id:
            return HttpResponseNotFound("A project id must be given.")
        try:
            proj = Project.objects.get(ldt_id=ldt_id)
        except Project.DoesNotExist:
            raise ObjectDoesNotExist("MashupHashcut : project not found. project_ldt_id = " + ldt_id)
        context = self.get_context_dict(request)
        context.update({"ldt_id":ldt_id, "proj": proj})
        return self.render_to_response(context)
    


class MashupContent(TemplateResponseMixin, MashupContextView):
    
    def get_template_names(self):
        return "mashup_content.html"
    
    def get(self, request, branding="iri", ctt_id=None, **kwargs):
        self.branding = branding
        if not ctt_id:
            return HttpResponseNotFound("A content id must be given.")
        try:
            content = Content.objects.get(iri_id=ctt_id)
        except Content.DoesNotExist:
            raise ObjectDoesNotExist("MashupContent : content not found. ctt_id = " + ctt_id)
        context = self.get_context_dict(request)
        context.update({"ctt_id":ctt_id, "content": content})
        return self.render_to_response(context)
    


class MashupProfile(TemplateResponseMixin, MashupContextView):
    
    def get_template_names(self):
        return "mashup_profile.html"
    
    def get(self, request, branding="iri", username=None, **kwargs):
        self.branding = branding
        if not username or username=="":
            return HttpResponseNotFound("A username must be given.")
        brd = Branding.objects.get(name=self.branding)
        try:
            user = User.objects.get(username=username)
        except:
            return HttpResponseNotFound("User not found.")
        mashups = Mashup.objects.filter(branding=brd, project__owner=user)
        
        context = self.get_context_dict(request)
        context.update({"username":username, "mashups":mashups})
        return self.render_to_response(context)
    


class MashupAllMashups(TemplateResponseMixin, MashupContextView):
    
    def get_template_names(self):
        return "mashup_all_mashups.html"
    
    def get(self, request, branding="iri", **kwargs):
        page = request.GET.get("page") or 1
        self.branding = branding
        brd = Branding.objects.get(name=self.branding)
        
        mashups = Mashup.objects.filter(branding=brd)
        nb = getattr(settings, 'LDT_FRONT_MEDIA_PER_PAGE', 9)
        if page=="x":
            nb = mashups.count()
        
        paginator = Paginator(mashups, nb)
        try:
            results = paginator.page(page)
        except (EmptyPage, InvalidPage):
            results = paginator.page(paginator.num_pages)
        
        context = self.get_context_dict(request)
        context.update({"results":results})
        return self.render_to_response(context)
    


class MashupAllContents(TemplateResponseMixin, MashupContextView):
    
    def get_template_names(self):
        return "mashup_all_contents.html"
    
    def get(self, request, branding="iri", **kwargs):
        page = request.GET.get("page") or 1
        self.branding = branding
        
        contents = Content.objects.filter(tags__icontains=branding)
        nb = getattr(settings, 'LDT_FRONT_MEDIA_PER_PAGE', 9)
        if page=="x":
            nb = contents.count()
        
        paginator = Paginator(contents, nb)
        try:
            results = paginator.page(page)
        except (EmptyPage, InvalidPage):
            results = paginator.page(paginator.num_pages)
        
        context = self.get_context_dict(request)
        context.update({"results":results})
        return self.render_to_response(context)
        
        

class MashupCreateUser(MashupHome):
    
    def get(self, request, branding="iri", **kwargs):
        return redirect('mashup_home', branding=branding)
    
    def post(self, request, branding="iri", **kwargs):
        if request.method == "POST":
            u_username = request.POST["signup-pseudo"]
            u_email = request.POST["signup-email"]
            u_pwd1 = request.POST["signup-password"]
            u_pwd2 = request.POST["signup-confirm-password"]
            if not re.match(r'^[a-zA-Z0-9]*$', u_username):
                return HttpResponse("Username not valid : only letters a-z A-Z and numbers.")
            if u_pwd1 == "" or u_pwd1 != u_pwd2:
                return HttpResponse("Password don't match.")
            u = None
            try:
                u = User.objects.get(username=u_username)
            except User.DoesNotExist:
                pass
            if u:
                return HttpResponse("Username already exists.")
            u = User.objects.create_user(u_username, u_email, u_pwd1)
            u.save()
            u_auth = authenticate(username=u.username, password=u_pwd1)
            if u_auth:
                login(request, u_auth)
                # We assign permission for the group associated to branding
                brd = Branding.objects.get(name=branding)
                grp = brd.group
                if grp:
                    u.groups.add(grp)
            else:
                return HttpResponse("Problem in authentication. User and password don't match.")
        return redirect('mashup_home', branding=branding)
        
        

class MashupIdenticateUser(MashupHome):
    
    def get(self, request, branding="iri", **kwargs):
        return redirect('mashup_home', branding=branding)
    
    def post(self, request, branding="iri", **kwargs):
        if request.method == "POST":
            u_username = request.POST["signup-pseudo"]
            u_pwd = request.POST["signup-password"]
            if u_username == "" or u_pwd == "":
                return HttpResponse("User and password don't match.")
            u_auth = authenticate(username=u_username, password=u_pwd)
            if u_auth:
                login(request, u_auth)
            else:
                return HttpResponse("Problem in authentication. User and password don't match.")
        return redirect('mashup_home', branding=branding)
        
        

class MashupLogOut(MashupHome):
    
    def get(self, request, branding="iri", **kwargs):
        logout(request)
        return redirect('mashup_home', branding=branding)
    
        
    
    