#
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
# BitBake Toaster Implementation
#
# Copyright (C) 2015        Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

from django.views.generic import View, TemplateView
from django.shortcuts import HttpResponse
from django.http import HttpResponseBadRequest
from django.core import serializers
from django.core.cache import cache
from django.core.paginator import Paginator, EmptyPage
from django.db.models import Q
from orm.models import Project, ProjectLayer, Layer_Version
from django.template import Context, Template
from django.core.serializers.json import DjangoJSONEncoder
from django.core.exceptions import FieldError
from django.conf.urls import url, patterns

import types
import json
import collections
import operator
import re

from toastergui.views import objtojson

class ToasterTable(TemplateView):
    def __init__(self, *args, **kwargs):
        super(ToasterTable, self).__init__()
        if 'template_name' in kwargs:
            self.template_name = kwargs['template_name']
        self.title = None
        self.queryset = None
        self.columns = []
        self.filters = {}
        self.total_count = 0
        self.static_context_extra = {}
        self.filter_actions = {}
        self.empty_state = "Sorry - no data found"
        self.default_orderby = ""

        # add the "id" column, undisplayable, by default
        self.add_column(title="Id",
                        displayable=False,
                        orderable=True,
                        field_name="id")


    def get(self, request, *args, **kwargs):
        if request.GET.get('format', None) == 'json':

            self.setup_queryset(*args, **kwargs)
            # Put the project id into the context for the static_data_template
            if 'pid' in kwargs:
                self.static_context_extra['pid'] = kwargs['pid']

            cmd = request.GET.get('cmd', None)
            if cmd and 'filterinfo' in cmd:
                data = self.get_filter_info(request, **kwargs)
            else:
                # If no cmd is specified we give you the table data
                data = self.get_data(request, **kwargs)

            return HttpResponse(data, content_type="application/json")

        return super(ToasterTable, self).get(request, *args, **kwargs)

    def get_filter_info(self, request, **kwargs):
        data = None

        self.setup_filters(**kwargs)

        search = request.GET.get("search", None)
        if search:
            self.apply_search(search)

        name = request.GET.get("name", None)
        if name is None:
            data = json.dumps(self.filters,
                              indent=2,
                              cls=DjangoJSONEncoder)
        else:
            for actions in self.filters[name]['filter_actions']:
                actions['count'] = self.filter_actions[actions['name']](count_only=True)

            # Add the "All" items filter action
            self.filters[name]['filter_actions'].insert(0, {
                'name' : 'all',
                'title' : 'All',
                'count' : self.queryset.count(),
            })

            data = json.dumps(self.filters[name],
                              indent=2,
                              cls=DjangoJSONEncoder)

            return data

    def setup_columns(self, *args, **kwargs):
        """ function to implement in the subclass which sets up the columns """
        pass
    def setup_filters(self, *args, **kwargs):
        """ function to implement in the subclass which sets up the filters """
        pass
    def setup_queryset(self, *args, **kwargs):
        """ function to implement in the subclass which sets up the queryset"""
        pass

    def add_filter(self, name, title, filter_actions):
        """Add a filter to the table.

        Args:
            name (str): Unique identifier of the filter.
            title (str): Title of the filter.
            filter_actions: Actions for all the filters.
        """
        self.filters[name] = {
          'title' : title,
          'filter_actions' : filter_actions,
        }

    def make_filter_action(self, name, title, action_function):
        """ Utility to make a filter_action """

        action = {
          'title' : title,
          'name' : name,
        }

        self.filter_actions[name] = action_function

        return action

    def add_column(self, title="", help_text="",
                   orderable=False, hideable=True, hidden=False,
                   field_name="", filter_name=None, static_data_name=None,
                   displayable=True, computation=None,
                   static_data_template=None):
        """Add a column to the table.

        Args:
            title (str): Title for the table header
            help_text (str): Optional help text to describe the column
            orderable (bool): Whether the column can be ordered.
                We order on the field_name.
            hideable (bool): Whether the user can hide the column
            hidden (bool): Whether the column is default hidden
            field_name (str or list): field(s) required for this column's data
            static_data_name (str, optional): The column's main identifier
                which will replace the field_name.
            static_data_template(str, optional): The template to be rendered
                as data
        """

        self.columns.append({'title' : title,
                             'help_text' : help_text,
                             'orderable' : orderable,
                             'hideable' : hideable,
                             'hidden' : hidden,
                             'field_name' : field_name,
                             'filter_name' : filter_name,
                             'static_data_name': static_data_name,
                             'static_data_template': static_data_template,
                             'displayable': displayable,
                             'computation': computation,
                            })

    def render_static_data(self, template, row):
        """Utility function to render the static data template"""

        context = {
          'extra' : self.static_context_extra,
          'data' : row,
        }

        context = Context(context)
        template = Template(template)

        return template.render(context)

    def apply_filter(self, filters, **kwargs):
        self.setup_filters(**kwargs)

        try:
            filter_name, filter_action = filters.split(':')
        except ValueError:
            return

        if "all" in filter_action:
            return

        try:
            self.filter_actions[filter_action]()
        except KeyError:
            # pass it to the user - programming error here
            raise

    def apply_orderby(self, orderby):
        # Note that django will execute this when we try to retrieve the data
        self.queryset = self.queryset.order_by(orderby)

    def apply_search(self, search_term):
        """Creates a query based on the model's search_allowed_fields"""

        if not hasattr(self.queryset.model, 'search_allowed_fields'):
            raise Exception("Err Search fields aren't defined in the model")

        search_queries = []
        for st in search_term.split(" "):
            q_map = [Q(**{field + '__icontains': st})
                     for field in self.queryset.model.search_allowed_fields]

            search_queries.append(reduce(operator.or_, q_map))

        search_queries = reduce(operator.and_, search_queries)

        self.queryset = self.queryset.filter(search_queries)


    def get_data(self, request, **kwargs):
        """Returns the data for the page requested with the specified
        parameters applied"""

        page_num = request.GET.get("page", 1)
        limit = request.GET.get("limit", 10)
        search = request.GET.get("search", None)
        filters = request.GET.get("filter", None)
        orderby = request.GET.get("orderby", None)

        # Make a unique cache name
        cache_name = self.__class__.__name__

        for key, val in request.GET.iteritems():
            cache_name = cache_name + str(key) + str(val)

        for key, val in kwargs.iteritems():
            cache_name = cache_name + str(key) + str(val)

        # No special chars allowed in the cache name apart from dash
        cache_name = re.sub(r'[^A-Za-z0-9-]', "", cache_name)
        data = cache.get(cache_name)

        if data:
            return data

        self.setup_columns(**kwargs)

        if search:
            self.apply_search(search)
        if filters:
            self.apply_filter(filters, **kwargs)
        if orderby:
            self.apply_orderby(orderby)

        paginator = Paginator(self.queryset, limit)

        try:
            page = paginator.page(page_num)
        except EmptyPage:
            page = paginator.page(1)

        data = {
            'total' : self.queryset.count(),
            'default_orderby' : self.default_orderby,
            'columns' : self.columns,
            'rows' : [],
            'error' : "ok",
        }

        try:
            for row in page.object_list:
                #Use collection to maintain the order
                required_data = collections.OrderedDict()

                for col in self.columns:
                    field = col['field_name']
                    if not field:
                        field = col['static_data_name']
                    if not field:
                        raise Exception("Must supply a field_name or static_data_name for column %s.%s" % (self.__class__.__name__,col))
                    # Check if we need to process some static data
                    if "static_data_name" in col and col['static_data_name']:
                        required_data["static:%s" % col['static_data_name']] = self.render_static_data(col['static_data_template'], row)

                        # Overwrite the field_name with static_data_name
                        # so that this can be used as the html class name

                        col['field_name'] = col['static_data_name']

                    # compute the computation on the raw data if needed
                    model_data = row
                    if col['computation']:
                        model_data = col['computation'](row)
                    else:
                        # Traverse to any foriegn key in the object hierachy
                        for subfield in field.split("__"):
                            if hasattr(model_data, subfield):
                                model_data = getattr(model_data, subfield)
                        # The field could be a function on the model so check
                        # If it is then call it
                        if isinstance(model_data, types.MethodType):
                          model_data = model_data()

                    required_data[col['field_name']] = model_data

                data['rows'].append(required_data)

        except FieldError:
            # pass  it to the user - programming-error here
            raise
        data = json.dumps(data, indent=2, default=objtojson)
        cache.set(cache_name, data, 60*30)

        return data


class ToasterTemplateView(TemplateView):
    # renders a instance in a template, or returns the context as json
    # the class-equivalent of the _template_renderer decorator for views

    def __init__(self, *args, **kwargs):
        super(ToasterTemplateView, self).__init__(*args, **kwargs)
        self.context_entries = []

    def get(self, *args, **kwargs):
        if self.request.GET.get('format', None) == 'json':
            from django.core.urlresolvers import reverse
            from django.shortcuts import HttpResponse
            from views import objtojson
            from toastergui.templatetags.projecttags import json as jsonfilter

            context = self.get_context_data(**kwargs)

            for x in context.keys():
                if x not in self.context_entries:
                    del context[x]

            context["error"] = "ok"

            return HttpResponse(jsonfilter(context,  default=objtojson ),
                            content_type = "application/json; charset=utf-8")

        return super(ToasterTemplateView, self).get(*args, **kwargs)

class ToasterTypeAhead(View):
    """ A typeahead mechanism to support the front end typeahead widgets """
    MAX_RESULTS = 6

    class MissingFieldsException(Exception):
        pass

    def __init__(self, *args, **kwargs):
        super(ToasterTypeAhead, self).__init__()

    def get(self, request, *args, **kwargs):
        def response(data):
            return HttpResponse(json.dumps(data,
                                           indent=2,
                                           cls=DjangoJSONEncoder),
                                content_type="application/json")

        error = "ok"

        search_term = request.GET.get("search", None)
        if search_term == None:
            # We got no search value so return empty reponse
            return response({'error' : error , 'results': []})

        try:
            prj = Project.objects.get(pk=kwargs['pid'])
        except KeyError:
            prj = None

        results = self.apply_search(search_term, prj, request)[:ToasterTypeAhead.MAX_RESULTS]

        if len(results) > 0:
            try:
                self.validate_fields(results[0])
            except MissingFieldsException as e:
                error = e

        data = { 'results' : results,
                'error' : error,
               }

        return response(data)

    def validate_fields(self, result):
        if 'name' in result == False or 'detail' in result == False:
            raise MissingFieldsException("name and detail are required fields")

    def apply_search(self, search_term, prj):
        """ Override this function to implement search. Return an array of
        dictionaries with a minium of a name and detail field"""
        pass
