from ldt.ldt_utils.contentindexer import add_segment, edit_segment
from ldt.ldt_utils.models import Project, Content
from ldt.ldt_utils.utils import LdtAnnotation
from ldt.security import protect_models, unprotect_models
from tastypie import fields
from tastypie.authorization import Authorization
from tastypie.exceptions import NotFound, BadRequest
from tastypie.resources import Resource


class AnnotationObject(object):
    def __init__(self, id="", project = "", type = "", type_title = "", ensemble="", media = "", begin = 0, end = 0, content = {"title":"", "description":""}, tags = [], meta = {"creator":"","created":""}):  # @ReservedAssignment
        self.id = id
        self.project = project
        self.type = type
        self.type_title = type_title
        self.ensemble = ensemble
        self.media = media
        self.begin = begin
        self.end = end
        self.content = content
        self.tags = tags
        self.meta = meta
    
class AnnotationResource(Resource):
    # For the moment, these attributes are useless. We just prepare relations to AnnotationObject
    id = fields.CharField(attribute = 'id')
    project = fields.CharField(attribute = 'project')
    type = fields.CharField(attribute = 'type')
    type_title = fields.CharField(attribute = 'type_title')
    media = fields.CharField(attribute = 'media')
    begin = fields.IntegerField(attribute = 'begin')
    end = fields.IntegerField(attribute = 'end')
    content = fields.DictField(attribute = 'content')
    tags = fields.ListField(attribute = 'tags')
    meta = fields.DictField(attribute = 'meta')
    
    class Meta:
        allowed_methods = ['post', 'put']
        resource_name = 'annotations'
        object_class = AnnotationObject
        authorization = Authorization()
        # always_return_data = True because we want the api returns the data with the updated ids
        always_return_data = True
        include_resource_uri = False
    
    def extract_annotation_data(self, data):
        # This method extracts and validates the data we receive from the user for adding or editing an annotation
        
        project_id = ""
        if data.has_key('project') :
            project_id = data["project"]
            
        if data.has_key('media') :
            iri_id = data["media"]
        else :
            raise BadRequest
        
        if project_id and project_id != "" :
            try:
                project = Project.objects.get(ldt_id=project_id)
            except Project.DoesNotExist:
                raise NotFound("Project not found. project_id = " + project_id)
        else :
            # If the project's is not defined, we get or create the content's front project.
            try:
                content = Content.objects.get(iri_id=iri_id)
            except Content.DoesNotExist:
                raise NotFound("Content not found. iri_id = " + iri_id)
            project = content.get_or_create_front_project()
            project_id = project.ldt_id
        
        ann_duration = str(data['end'] - data['begin'])
        ann_begin = str(data['begin'])
        ann_end = str(data['end'])
        # We test if the annotation has audio node
        ann_audio_src = ""
        ann_audio_href = ""
        if data['content'].has_key('audio') :
            if data['content']['audio'].has_key('src') :
                ann_audio_src = data['content']['audio']['src']
            if data['content']['audio'].has_key('href') :
                ann_audio_href = data['content']['audio']['href']
        
        ann_author = data['meta']['creator']
        ann_date = data['meta']['created']
        
        ann_type_id = data.get('type', '')
        ann_type_title = data.get('type_title', '')
        ann_id = data.get("id", "")
        ann_title = data.get('content', {}).get('title', "") 
        ann_description = data.get('content', {}).get('description')
        ann_tags = data.get('tags', [])
        
        content = project.contents.get(iri_id=iri_id)
        
        return {
            "project_obj" : project,
            "project_id" : project_id,
            "content_obj" : content,  
            "iri_id" : iri_id,
            "ann_type_id" : ann_type_id, 
            "ann_type_title" : ann_type_title,
            "ann_id" : ann_id,
            "ann_content" : { 
                "title" : ann_title, 
                "description" : ann_description,
                "audio" : {
                    "src" : ann_audio_src,
                    "href" : ann_audio_href,
                },
            },
            "ann_meta" : {
                "creator" : ann_author,
                "created" : ann_date,
            },
            "ann_tags" : ann_tags,
            "ann_begin" : ann_begin,
            "ann_end" : ann_end,
            "ann_duration" : ann_duration,
        }
    
    def obj_delete_list(self, bundle, **kwargs):
        return True
    
    def obj_create(self, bundle, **kwargs):
        # Here the a has the datas for only one annotation. Tastypie's post allows only one resource addition 
        data_dict = self.extract_annotation_data(bundle.data)
        adder = LdtAnnotation(data_dict["project_obj"])
        unprotect_models() # Allows anonymous user to modify models in this request only
        
        type_id, new_id, ensemble_id = adder.add(
            data_dict['iri_id'], # media
            data_dict['ann_type_id'], # cutting_id
            data_dict['ann_type_title'], # cutting_title
            data_dict['ann_content']['title'], # title
            data_dict['ann_content']['description'], # text
            data_dict['ann_tags'], # tags_list
            data_dict['ann_begin'], # begin
            data_dict['ann_duration'], # dur
            data_dict['ann_meta']['creator'], # author
            data_dict['ann_meta']['created'], # date
            None, 
            "2194379", 
            data_dict['ann_content']['audio']['src'], 
            data_dict['ann_content']['audio']['href']
        )
        if not new_id:
            protect_models()
            raise BadRequest
                        
        # We update the ids
        data_dict['ann_type_id'] = type_id
        data_dict['ensemble_id'] = ensemble_id
        data_dict['ann_id'] = new_id

        #add segment
        add_segment({
            "project" : data_dict["project_obj"],
            "content" : data_dict["content_obj"],
            "ensemble_id" : data_dict["ensemble_id"],
            "cutting_id" :  data_dict['ann_type_id'],            
            "element_id" : data_dict['ann_id'],
            "title" : data_dict['ann_content']['title'],
            "abstract" : data_dict['ann_content']['description'],
            "tags" : ",".join(data_dict['ann_tags']),
            "start_ts" : data_dict['ann_begin'],
            "duration" :  data_dict['ann_duration'],
            "author" : data_dict['ann_meta']['creator'],
            "date" : data_dict['ann_meta']['created'], 
            "audio_src" : data_dict['ann_content']['audio']['src'],            
            "audio_href" : data_dict['ann_content']['audio']['href'],
            "polemics": adder.get_polemic_syntax(data_dict['ann_content']['title'])
        })
            
        # We save the added annotation and reprotect the contents and projects
        adder.save(must_reindex=False)
        protect_models()
        # We update the AnnotationObject for the returned datas to be correct.
        bundle.obj = AnnotationObject(
            id = data_dict["ann_id"], 
            project = data_dict["project_id"], 
            type = data_dict["ann_type_id"], 
            type_title = data_dict["ann_type_title"], 
            ensemble = data_dict['ensemble_id'], 
            media = data_dict["iri_id"], 
            begin = data_dict["ann_begin"], 
            end = data_dict["ann_end"], 
            content = data_dict['ann_content'], 
            tags = data_dict['ann_tags'], 
            meta = data_dict['ann_meta']
        )
        return bundle
    
    def obj_update(self, bundle, **kwargs):
        data_dict = self.extract_annotation_data(bundle.data)
        adder = LdtAnnotation(data_dict["project_obj"])
        unprotect_models() # Allows anonymous user to modify models in this request only
        
        ensemble_id = adder.edit(
            data_dict['ann_id'], # annotation_id
            data_dict['iri_id'], # media
            data_dict['ann_type_id'], # cutting_id
            data_dict['ann_type_title'], # cutting_title
            data_dict['ann_content']['title'], # title
            data_dict['ann_content']['description'], # text
            data_dict['ann_tags'], # tags_list
            data_dict['ann_begin'], # begin
            data_dict['ann_duration'], # dur
            data_dict['ann_meta']['creator'], # author
            data_dict['ann_meta']['created'], # date
            None, 
            "2194379", 
            data_dict['ann_content']['audio']['src'], 
            data_dict['ann_content']['audio']['href']
        )
        if not ensemble_id:
            protect_models()
            raise BadRequest
        
        # We update the id
        data_dict['ensemble_id'] = ensemble_id
        
        #add segment
        edit_segment(
            data_dict["project_id"],
            data_dict["iri_id"],
            data_dict["ensemble_id"],
            data_dict['ann_type_id'],
            data_dict["ann_id"],
            params = {
                "project" : data_dict["project_obj"],
                "content" : data_dict["content_obj"],
                "ensemble_id" : data_dict["ensemble_id"],
                "cutting_id" :  data_dict['ann_type_id'],            
                "element_id" : data_dict['ann_id'],
                "title" : data_dict['ann_content']['title'],
                "abstract" : data_dict['ann_content']['description'],
                "tags" : ",".join(data_dict['ann_tags']),
                "start_ts" : data_dict['ann_begin'],
                "duration" :  data_dict['ann_duration'],
                "author" : data_dict['ann_meta']['creator'],
                "date" : data_dict['ann_meta']['created'], 
                "audio_src" : data_dict['ann_content']['audio']['src'],            
                "audio_href" : data_dict['ann_content']['audio']['href'],
                "polemics": adder.get_polemic_syntax(data_dict['ann_content']['title'])
            })
        # We save the added annotation and reprotect the contents and projects
        adder.save(must_reindex=False)
        protect_models()
        # We update the AnnotationObject for the returned datas to be correct.
        bundle.obj = AnnotationObject(
            id = data_dict["ann_id"], 
            project = data_dict["project_id"], 
            type = data_dict["ann_type_id"], 
            type_title = data_dict["ann_type_title"], 
            ensemble = data_dict['ensemble_id'], 
            media = data_dict["iri_id"], 
            begin = data_dict["ann_begin"], 
            end = data_dict["ann_end"], 
            content = data_dict['ann_content'], 
            tags = data_dict['ann_tags'], 
            meta = data_dict['ann_meta']
        )
        return bundle
    
    def get_resource_uri(self, bundle_or_obj=None, url_name='api_dispatch_list'):
        return ''

    