from models import Module, ModuleTab
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.contrib.contenttypes.models import ContentType
from ox.django.shortcuts import render_to_json_response
import re
from django.http import HttpResponse, HttpResponseRedirect
from settings import PROJECT_ROOT
from os.path import join, exists

def add_object(request, module_slug, tab_slug):
    tab = get_object_or_404(ModuleTab, slug=tab_slug)
    model_class = tab.model_class()
    add_form_name = model_class.main_form
    form = model_class.get_forms()[add_form_name]
    if request.POST:
        f = form(request.POST, request.FILES)
        #import pdb
        #pdb.set_trace()        
        if f.is_valid():
            instance = f.save(commit=False)
            if instance.__dict__.has_key('added_by_id'): #FIXME: add user.is_authenticated() ..
                instance.added_by = request.user
            instance.save()
            inlines = [inline(request.POST, request.FILES, instance=instance) for inline in f.inlines]
            all_valid = True
            for inline in inlines:
                if inline.is_valid():
                    inline.save()
                else:
                    all_valid = False
            if all_valid:
                return HttpResponseRedirect(instance.get_absolute_url())
#            else:
#                inlines = [inline(instance=instance) for inline in f.inlines]    
        else:
            inlines = [inline() for inline in f.inlines]    
    else:
        f = form()
        inlines = [inline() for inline in f.inlines]

#    import pdb
#    pdb.set_trace()
    context = RequestContext(request, {
        'form': f,
        'inlines': inlines,
        'errors': f.errors,
        'new': True
    })
    return render_to_response("test/person_form.html", context)


def edit_object(request, module_slug, tab_slug, object_id):
    tab = get_object_or_404(ModuleTab, slug=tab_slug)
    model_class = tab.model_class()
    obj = get_object_or_404(model_class, pk=object_id)
    content_type_id = ContentType.objects.get_for_model(model_class).id
    add_form_name = model_class.main_form
    form = model_class.get_forms()[add_form_name]
    galleries = obj.galleries.all()        
   
    if request.POST:
        f = form(request.POST, request.FILES, instance=obj)
        #FIXME: if obj.user_has_perms(request.user): .. else return error .. 
        inlines = [inline(request.POST, request.FILES, instance=obj) for inline in f.inlines]
        if f.is_valid():
            instance = f.save()
            all_valid = True
            for inline in inlines:
                if inline.is_valid():
                    inline.save()
                else:
                    all_valid = False
            if all_valid:
                return HttpResponseRedirect(instance.get_absolute_url())
        #else:
            #f = form(instance=obj)
            #inlines = [inline(instance=obj) for inline in f.inlines]
    else:
            f = form(instance=obj)
            inlines = [inline(instance=obj) for inline in f.inlines]        
    context = RequestContext(request, {
        'form': f,
        'object': obj,
        'content_type_id': content_type_id,
        'inlines': inlines,
        'galleries': galleries,
        'new': False
    })
    return render_to_response("test/person_form.html", context)


def render_object(request, module_slug):
    '''
    Main function that handles incoming requests:
    http://<website>/m/<module_name>/<tab_name>/?object_id=<x>&search=<search_term>&sort=<sort_string>&page=<page_no>&count=<items_per_page>
        
    All options / parameters after <module_name> are optional.

    '''
    #Get the module from module slug in URL, else return a 404
    module = get_object_or_404(Module, slug=module_slug)

    #If there is a tab slug in the URL, fetch that tab, else fetch the default tab, else get the first of all tabs
    tab_slug = request.GET.get("tab", '')
    try:
        tab = get_object_or_404(ModuleTab, slug=tab_slug)
    except:
        try:
            tab = module.moduletab_set.filter(is_default=True)[0]
        except:
            tab = module.moduletab_set.all()[0]

    #Get the model class associated with the tab
    model_class = tab.model_class()

    #Get various options from GET params
    try:
        object_id = int(request.GET.get("object_id", 0))
    except:
        object_id = 0

    sortString = request.GET.get("sort", "")
    if sortString == "" or sortString == 'null':
        sortArray = []
    else:
        sortOperator = sortString[0]
        sortField = sortString[1:]
        sortArray = [{
            'operator': sortOperator,
            'key': sortField
        }]
    list_options = {
        'search': request.GET.get("search", ""),
        'sort': sortArray, 
        'page': request.GET.get("page", 1),
        'object_id': object_id,
        'count': request.GET.get("count", 15) #FIXME: make list_length either in settings.py or config per model
    }

    #Call get_list method on the tab to get a list of all items in the list
    object_list = tab.get_list(list_options)

    #If no object_id was provided, select the first object in the list
    if object_id == 0:       
        object_id = object_list['items'][0]['id']

    #Fetch the object whose details to display - if the result list is empty, handle displaying a No Results page to the user
    if object_list['has_results']:
        obj = get_object_or_404(model_class, pk=object_id)
        item_data = obj.insidepage_dict(request)
    else: #We create a 'fake' object with properties that we require the template to render No results found, FIXME: should be a cleaner way to perhaps render a separate template with the list of items on the left and saying "No Results Found" - however, this works for now.
        obj = {
            'get_title': 'No Results Found',
            'get_absolute_url': tab.get_absolute_url(),
            'get_add_url': None
        }
        item_data = {
            'html': 'The search query you entered did not return any results.'
        } 

 
    
    #Get all the context and render to template
    context = RequestContext(request, {
        'item': obj, #The object to be rendered
        'item_data': item_data, #custom object data got from the .insidepage_dict method on the model class
        'tab': tab, #the tab object
        'object_list': object_list, #Pagination object, list of items for left list.
        'tabs': tab.module.moduletab_set.all() #All the tabs of the current module
    })
    return render_to_response("noel/render_object.html", context)


def test_template(request, template_name):
    test_path = join(PROJECT_ROOT, "templates", "test_static_templates")
    template_path = join(test_path, template_name + ".html")
    if exists(template_path):
        html = open(template_path).read()
    else:
        html = "Template not found."
    context = RequestContext(request, {
        'item': {},
        'item_data': {'html': html},
        'tab': {},
        'object_list': [],
        'tabs': []
    })
    return render_to_response("noel/render_object.html", context)

######
#HERE BE OLD DISCARED CODE:
#####
#def main(request, module_slug):
#    m = get_object_or_404(Module, slug=module_slug)
#    tabs = m.moduletab_set.all().order_by('order')
#    default_tab = tabs[0]
#    try:
#        formStr = default_tab.model_class().add_form        
#        has_add = True
#        add_form_class = default_tab.model_class().get_add_form()
#        add_form = add_form_class()	
#    except:
#        add_form = None
#        has_add = False

#    list_options = {} #get some options as GET params, etc. to potentially pass to get_list
#    default_tab_list = default_tab.model_class().get_list(list_options)
#    context = RequestContext(request, {
#        'title': m.title,
#        'about': m.about,
#        'has_add': has_add,
#        'add_form': add_form,
#        'default_tab': tabs[0],
#        'default_list': default_tab_list,
#        'default_sorts': default_tab.get_dict()['sorts'],
#        'tabs': tabs[1:]
#    })
#    return render_to_response("noel/insidepage.html", context)


#def get_tab(request):
#    tab_slug = request.GET.get("tab", "")
#    tab = get_object_or_404(ModuleTab, slug=tab_slug)
#    return render_to_json_response(tab.get_dict())
#           


#def get_list(request):
#    numre = re.compile("[0-9]*")
#    tab_slug = request.GET.get("tab", "")
#    tab = get_object_or_404(ModuleTab, slug=tab_slug)
#    object_id = request.GET.get("object_id", False)
#    object_id = object_id[numre.match(object_id).start():numre.match(object_id).end()] #FIXME - why is the front-end sending this?
#    sortString = request.GET.get("sort", "")
#    if sortString == "" or sortString == 'null':
#        sortArray = []
#    else:
#        sortOperator = sortString[0]
#        sortField = sortString[1:]
#        sortArray = [{
#            'operator': sortOperator,
#            'key': sortField
#        }]

#    list_options = {
#        'search': request.GET.get("search", ""),
#        'sort': sortArray, 
#        'page': request.GET.get("page", 1),
#        'object_id': object_id,
#        'count': request.GET.get("count", 15) #FIXME: make list_length either in settings.py or config per model
#    }
#    object_list = tab.get_list(list_options)
#    return render_to_json_response(object_list)


#def get_details(request):
##    import pdb
#    tab_slug = request.GET.get("tab", '')
#    tab = get_object_or_404(ModuleTab, slug=tab_slug)
#    model_class = tab.model_class()
#    object_id = request.GET.get("object_id", 0)
#    obj = get_object_or_404(model_class, pk=object_id)
#    ret = obj.insidepage_dict(request)
##    ret['csrf_token'] = c
##    pdb.set_trace()
#    return render_to_json_response(ret)


