from itertools import groupby
from ldt.api.ldt.authentication import (SessionAuthentication, ApiKeyAuthentication)
from ldt.indexation import get_results_list
from ldt.ldt_utils.models import Content, Media, Project, Segment
from ldt.ldt_utils.projectserializer import ProjectJsonSerializer
from ldt.ldt_utils.modelsutils  import ProjectMerger
from ldt.security import unprotect_models, protect_models
import logging

from django.conf.urls import url
from django.contrib.auth.models import Group
from django.shortcuts import get_object_or_404
from guardian.shortcuts import get_objects_for_group
from tastypie import fields
from tastypie.authentication import MultiAuthentication
from tastypie.resources import Bundle, ModelResource, ALL_WITH_RELATIONS, ALL


logger = logging.getLogger(__name__)

class MediaResource(ModelResource):

    class Meta:
        allowed_methods = ['get']
        resource_name = 'medias'
        queryset = Media.objects.all()

    def get_resource_uri(self, bundle_or_obj=None, url_name='api_dispatch_list'):
        if not bundle_or_obj:
            return super(MediaResource, self).get_resource_uri(bundle_or_obj,url_name)
        elif isinstance(bundle_or_obj, Bundle):
            return bundle_or_obj.obj.videopath + bundle_or_obj.obj.stream_src
        else:
            return bundle_or_obj.videopath + bundle_or_obj.stream_src

class ContentResource(ModelResource):

    front_project = fields.ForeignKey('ldt.api.ldt.resources.ProjectResource','front_project', null=True, full=False)
    media_url = fields.ForeignKey('ldt.api.ldt.resources.content.MediaResource','media_obj', null=True, full=False)

    class Meta:
        allowed_methods = ['get']
        resource_name = 'contents'
        authentication = MultiAuthentication(ApiKeyAuthentication(), SessionAuthentication())
        queryset = Content.objects.select_related('front_project','media_obj').all()
        filtering = {
            'tags' : ALL_WITH_RELATIONS,
            'title' : ALL,
        }
        ordering = ['title', 'creation_date', 'content_creation_date']

    def get_object_list(self, request):
        return Content.safe_objects.select_related('front_project', 'media_obj').all()

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/recommended/$" % self._meta.resource_name, self.wrap_view('get_recommended'), name="api_contents_recommended"),
            url(r"^(?P<resource_name>%s)/all/(?P<iri_id>[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('get_all_projects'), name="api_content_all_projects"),
            url(r"^(?P<resource_name>%s)/(?P<iri_id>[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
        ]

    def get_resource_uri(self, bundle_or_obj=None, url_name='api_dispatch_list'):
        if bundle_or_obj is None:
            return super(ContentResource, self).get_resource_uri(bundle_or_obj, url_name)
        kwargs = {
            'resource_name': self._meta.resource_name,
            'api_name': self._meta.api_name
        }
        if isinstance(bundle_or_obj, Bundle):
            kwargs['iri_id'] = bundle_or_obj.obj.iri_id
        else:
            kwargs['iri_id'] = bundle_or_obj.iri_id
        return self._build_reverse_url("api_dispatch_detail", kwargs=kwargs)

    def get_recommended(self, request, **kwargs):
        self.method_check(request, allowed=['get'])

        keywords = request.GET.get('keywords','')
        keywords_search = " OR ".join(keywords.split(','))
        field = request.GET.get('field','all')

        result_list = get_results_list(Segment, field, keywords_search)
        score_dict = dict([(k,sum([e.score for e in i])) for k,i in groupby(result_list, lambda e: e.iri_id)])

        res = [self.full_dehydrate(self.build_bundle(obj=c, request=request)) for c in Content.safe_objects.filter(iri_id__in = score_dict.keys())]

        def add_score(b,s):
            b.data['score'] = s
            return b

        object_list = {
            'objects': sorted([add_score(b, score_dict.get(b.data['iri_id'],0)) for b in res], key=lambda b: b.data['score'], reverse=True),
        }

        self.log_throttled_access(request)

        return  self.create_response(request, object_list)

    def get_all_projects(self, request, api_name, resource_name, iri_id=None):
        self.method_check(request, allowed=['get'])
        content = get_object_or_404(Content, iri_id=iri_id)

        # Unprotect the time to build the project
        unprotect_models()

        # add filter
        group_id = request.GET.get("group")
        if group_id is not None :
            group = get_object_or_404(Group, id=group_id)
            projects = get_objects_for_group(group, "view_project", Project.objects.filter(contents__in=[content], state=2))
        else:
            projects = Project.objects.filter(contents__in=[content], state=2)

        pm = ProjectMerger(content, projects)
        proj = pm.get_merged_project(False)
        ps = ProjectJsonSerializer(proj)
        data = ps.serialize_to_cinelab()
        self.log_throttled_access(request)
        # Delete project because it is useless to keep it in database
        # TODO: remove this, this is ugly. The project object should not be created
        proj.delete()

        protect_models()

        return self.create_response(request, data)
