import logging

from django.conf import settings
from django.conf.urls import url
from django.core.paginator import Paginator, InvalidPage
from django.db.models import F, Q
from tastypie.constants import ALL
from tastypie.exceptions import BadRequest, NotFound
from tastypie.resources import ModelResource
from tastypie.utils import trailing_slash

from ldt.indexation import get_results_list
from ldt.ldt_utils.models import Content, Segment
from ldt.ldt_utils.segmentserializer import SegmentSerializer


logger = logging.getLogger(__name__)

class SegmentResource(ModelResource):
    class Meta:
        allowed_methods = ['get']
        resource_name = 'segments'
        excludes = ['project_obj', 'content']
        queryset = Segment.objects.all()
        filtering = {
            'iri_id': ALL,
            'start_ts': ALL,
        }
    
#    # WARNING : this segment API will only return json format, no matter format get parameter.
#    def determine_format(self, request):
#        return "application/json"
    
    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/search%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_search'), name="api_get_search"),
            url(r"^(?P<resource_name>%s)/bytimecode%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_segments_by_timecode'), name='segment_api_empty'),
            url(r"^(?P<resource_name>%s)/bytimecode/(?P<iri_id>.*)/(?P<begin>.*)/(?P<end>.*)$" % self._meta.resource_name, self.wrap_view('get_segments_by_timecode'), name='segment_api'),
        ]

    def get_search(self, request, **kwargs):
        self.method_check(request, allowed=['get'])
        # Do the query.
        search = request.GET.get('q', '')
        if search=='':
            raise BadRequest('The request needs a search query "q=" parameter.')
        field = "all"
        if u'author:' in search.lower() :
            sub = search[7:]
            sub = sub.upper()
            if sub[0] != u'"':
                sub = u'"' + sub
            if sub[-1] != u'"':
                sub = sub + u'"'
            search = u'author:' + sub
        
        results = get_results_list(Segment, field, search, False)
        # get_results_list returns a SearchQuerySet, we load_all() to get all real Segment objects 
        all_segments = results.load_all()
        paginator = Paginator(all_segments, request.GET.get("limit") or getattr(settings, 'API_LIMIT_PER_PAGE', 20))
        
        try:
            page = paginator.page(int(request.GET.get('page', 1)))
        except InvalidPage:
            raise NotFound("Sorry, no results on that page.")
        
        objects = []
        
        for search_res in page.object_list:
            # search_res is a SearchResult, search_res.object is the real Segment Object thanks to results.load_all()
            bundle = self.build_bundle(obj=search_res.object, request=request)
            bundle = self.full_dehydrate(bundle)
            objects.append(bundle)
        
        object_list = {
            'objects': objects,
        }

        self.log_throttled_access(request)
        return self.create_response(request, object_list)
    
    
    
    def get_segments_by_timecode(self, request, api_name, resource_name, iri_id=None, begin=None, end=None):
        """
        returns segments about content iri_id between timecodes begin and end
        """
        if not begin:
            raise NotFound("begin timecode argument is missing.")
        if not end:
            raise NotFound("end timecode argument is missing.")
        begin = int(begin)
        end = int(end)
        
        content = Content.objects.filter(iri_id=iri_id).select_related('media_obj', 'stat_annotation')
        if not content:
            raise NotFound("Content does not exist or id is not correct.")
        content = content[0]
        
        segments = Segment.objects.filter(content=content).filter(
                    Q(start_ts__gte=begin, start_ts__lte=end) |                            # segment starts between begin and end
                    Q(start_ts__gte=begin-F('duration'), start_ts__lte=end-F('duration')) |# segment ends between begin and end
                    Q(start_ts__lte=begin, start_ts__gte=end-F('duration'))                # period [begin:end] is included in the segment
                    ).select_related("project_obj")
        
        a = SegmentSerializer(content, segments)
        return self.create_response(request, a.serialize_to_cinelab())
    