import cgi, datetime, re, time, urllib
from django import http
import django.core.exceptions
from django.core import urlresolvers
from django.utils import datastructures
import simplejson
from autotest_lib.frontend.shared import exceptions, query_lib
from autotest_lib.frontend.afe import model_logic


_JSON_CONTENT_TYPE = 'application/json'


def _resolve_class_path(class_path):
    module_path, class_name = class_path.rsplit('.', 1)
    module = __import__(module_path, {}, {}, [''])
    return getattr(module, class_name)


_NO_VALUE_SPECIFIED = object()

class _InputDict(dict):
    def get(self, key, default=_NO_VALUE_SPECIFIED):
        return super(_InputDict, self).get(key, default)


    @classmethod
    def remove_unspecified_fields(cls, field_dict):
        return dict((key, value) for key, value in field_dict.iteritems()
                    if value is not _NO_VALUE_SPECIFIED)


class Resource(object):
    _permitted_methods = None # subclasses must override this


    def __init__(self, request):
        assert self._permitted_methods
        # this request should be used for global environment info, like
        # constructing absolute URIs.  it should not be used for query
        # parameters, because the request may not have been for this particular
        # resource.
        self._request = request
        # this dict will contain the applicable query parameters
        self._query_params = datastructures.MultiValueDict()


    @classmethod
    def dispatch_request(cls, request, *args, **kwargs):
        # handle a request directly
        try:
            try:
                instance = cls.from_uri_args(request, **kwargs)
            except django.core.exceptions.ObjectDoesNotExist, exc:
                raise http.Http404(exc)

            instance.read_query_parameters(request.GET)
            return instance.handle_request()
        except exceptions.RequestError, exc:
            return exc.response


    def handle_request(self):
        if self._request.method.upper() not in self._permitted_methods:
            return http.HttpResponseNotAllowed(self._permitted_methods)

        handler = getattr(self, self._request.method.lower())
        return handler()


    # the handler methods below only need to be overridden if the resource
    # supports the method

    def get(self):
        """Handle a GET request.

        @returns an HttpResponse
        """
        raise NotImplementedError


    def post(self):
        """Handle a POST request.

        @returns an HttpResponse
        """
        raise NotImplementedError


    def put(self):
        """Handle a PUT request.

        @returns an HttpResponse
        """
        raise NotImplementedError


    def delete(self):
        """Handle a DELETE request.

        @returns an HttpResponse
        """
        raise NotImplementedError


    @classmethod
    def from_uri_args(cls, request, **kwargs):
        """Construct an instance from URI args.

        Default implementation for resources with no URI args.
        """
        return cls(request)


    def _uri_args(self):
        """Return kwargs for a URI reference to this resource.

        Default implementation for resources with no URI args.
        """
        return {}


    def _query_parameters_accepted(self):
        """Return sequence of tuples (name, description) for query parameters.

        Documents the available query parameters for GETting this resource.
        Default implementation for resources with no parameters.
        """
        return ()


    def read_query_parameters(self, parameters):
        """Read relevant query parameters from a Django MultiValueDict."""
        params_acccepted = set(param_name for param_name, _
                               in self._query_parameters_accepted())
        for name, values in parameters.iterlists():
            base_name = name.split(':', 1)[0]
            if base_name in params_acccepted:
                self._query_params.setlist(name, values)


    def set_query_parameters(self, **parameters):
        """Set query parameters programmatically."""
        self._query_params.update(parameters)


    def href(self, query_params=None):
        """Return URI to this resource."""
        kwargs = self._uri_args()
        path = urlresolvers.reverse(self.dispatch_request, kwargs=kwargs)
        full_query_params = datastructures.MultiValueDict(self._query_params)
        if query_params:
            full_query_params.update(query_params)
        if full_query_params:
            path += '?' + urllib.urlencode(full_query_params.lists(),
                                           doseq=True)
        return self._request.build_absolute_uri(path)


    def resolve_uri(self, uri):
        # check for absolute URIs
        match = re.match(r'(?P<root>https?://[^/]+)(?P<path>/.*)', uri)
        if match:
            # is this URI for a different host?
            my_root = self._request.build_absolute_uri('/')
            request_root = match.group('root') + '/'
            if my_root != request_root:
                # might support this in the future, but not now
                raise exceptions.BadRequest('Unable to resolve remote URI %s'
                                            % uri)
            uri = match.group('path')

        try:
            view_method, args, kwargs = urlresolvers.resolve(uri)
        except http.Http404:
            raise exceptions.BadRequest('Unable to resolve URI %s' % uri)
        resource_class = view_method.im_self # class owning this classmethod
        return resource_class.from_uri_args(self._request, **kwargs)


    def resolve_link(self, link):
        if isinstance(link, dict):
            uri = link['href']
        elif isinstance(link, basestring):
            uri = link
        else:
            raise exceptions.BadRequest('Unable to understand link %s' % link)
        return self.resolve_uri(uri)


    def link(self, query_params=None):
        return {'href': self.href(query_params=query_params)}


    def _query_parameters_response(self):
        return dict((name, description)
                    for name, description in self._query_parameters_accepted())


    def _basic_response(self, content):
        """Construct and return a simple 200 response."""
        assert isinstance(content, dict)
        query_parameters = self._query_parameters_response()
        if query_parameters:
            content['query_parameters'] = query_parameters
        encoded_content = simplejson.dumps(content)
        return http.HttpResponse(encoded_content,
                                 content_type=_JSON_CONTENT_TYPE)


    def _decoded_input(self):
        content_type = self._request.META.get('CONTENT_TYPE',
                                              _JSON_CONTENT_TYPE)
        raw_data = self._request.raw_post_data
        if content_type == _JSON_CONTENT_TYPE:
            try:
                raw_dict = simplejson.loads(raw_data)
            except ValueError, exc:
                raise exceptions.BadRequest('Error decoding request body: '
                                            '%s\n%r' % (exc, raw_data))
            if not isinstance(raw_dict, dict):
                raise exceptions.BadRequest('Expected dict input, got %s: %r' %
                                            (type(raw_dict), raw_dict))
        elif content_type == 'application/x-www-form-urlencoded':
            cgi_dict = cgi.parse_qs(raw_data) # django won't do this for PUT
            raw_dict = {}
            for key, values in cgi_dict.items():
                value = values[-1] # take last value if multiple were given
                try:
                    # attempt to parse numbers, booleans and nulls
                    raw_dict[key] = simplejson.loads(value)
                except ValueError:
                    # otherwise, leave it as a string
                    raw_dict[key] = value
        else:
            raise exceptions.RequestError(415, 'Unsupported media type: %s'
                                          % content_type)

        return _InputDict(raw_dict)


    def _format_datetime(self, date_time):
        """Return ISO 8601 string for the given datetime"""
        if date_time is None:
            return None
        timezone_hrs = time.timezone / 60 / 60  # convert seconds to hours
        if timezone_hrs >= 0:
            timezone_join = '+'
        else:
            timezone_join = '' # minus sign comes from number itself
        timezone_spec = '%s%s:00' % (timezone_join, timezone_hrs)
        return date_time.strftime('%Y-%m-%dT%H:%M:%S') + timezone_spec


    @classmethod
    def _check_for_required_fields(cls, input_dict, fields):
        assert isinstance(fields, (list, tuple)), fields
        missing_fields = ', '.join(field for field in fields
                                   if field not in input_dict)
        if missing_fields:
            raise exceptions.BadRequest('Missing input: ' + missing_fields)


class Entry(Resource):
    @classmethod
    def add_query_selectors(cls, query_processor):
        """Sbuclasses may override this to support querying."""
        pass


    def short_representation(self):
        return self.link()


    def full_representation(self):
        return self.short_representation()


    def get(self):
        return self._basic_response(self.full_representation())


    def put(self):
        try:
            self.update(self._decoded_input())
        except model_logic.ValidationError, exc:
            raise exceptions.BadRequest('Invalid input: %s' % exc)
        return self._basic_response(self.full_representation())


    def _delete_entry(self):
        raise NotImplementedError


    def delete(self):
        self._delete_entry()
        return http.HttpResponse(status=204) # No content


    def create_instance(self, input_dict, containing_collection):
        raise NotImplementedError


    def update(self, input_dict):
        raise NotImplementedError


class InstanceEntry(Entry):
    class NullEntry(object):
        def link(self):
            return None


        def short_representation(self):
            return None


    _null_entry = NullEntry()
    _permitted_methods = ('GET', 'PUT', 'DELETE')
    model = None # subclasses must override this with a Django model class


    def __init__(self, request, instance):
        assert self.model is not None
        super(Entry, self).__init__(request)
        self.instance = instance
        self._is_prepared_for_full_representation = False


    @classmethod
    def from_optional_instance(cls, request, instance):
        if instance is None:
            return cls._null_entry
        return cls(request, instance)


    def _delete_entry(self):
        self.instance.delete()


    def full_representation(self):
        self.prepare_for_full_representation([self])
        return super(InstanceEntry, self).full_representation()


    @classmethod
    def prepare_for_full_representation(cls, entries):
        """
        Prepare the given list of entries to generate full representations.

        This method delegates to _do_prepare_for_full_representation(), which
        subclasses may override as necessary to do the actual processing.  This
        method also marks the instance as prepared, so it's safe to call this
        multiple times with the same instance(s) without wasting work.
        """
        not_prepared = [entry for entry in entries
                        if not entry._is_prepared_for_full_representation]
        cls._do_prepare_for_full_representation([entry.instance
                                                 for entry in not_prepared])
        for entry in not_prepared:
            entry._is_prepared_for_full_representation = True


    @classmethod
    def _do_prepare_for_full_representation(cls, instances):
        """
        Subclasses may override this to gather data as needed for full
        representations of the given model instances.  Typically, this involves
        querying over related objects, and this method offers a chance to query
        for many instances at once, which can provide a great performance
        benefit.
        """
        pass


class Collection(Resource):
    _DEFAULT_ITEMS_PER_PAGE = 50

    _permitted_methods=('GET', 'POST')

    # subclasses must override these
    queryset = None # or override _fresh_queryset() directly
    entry_class = None


    def __init__(self, request):
        super(Collection, self).__init__(request)
        assert self.entry_class is not None
        if isinstance(self.entry_class, basestring):
            type(self).entry_class = _resolve_class_path(self.entry_class)

        self._query_processor = query_lib.QueryProcessor()
        self.entry_class.add_query_selectors(self._query_processor)


    def _query_parameters_accepted(self):
        params = [('start_index', 'Index of first member to include'),
                  ('items_per_page', 'Number of members to include'),
                  ('full_representations',
                   'True to include full representations of members')]
        for selector in self._query_processor.selectors():
            params.append((selector.name, selector.doc))
        return params


    def _fresh_queryset(self):
        assert self.queryset is not None
        # always copy the queryset before using it to avoid caching
        return self.queryset.all()


    def _entry_from_instance(self, instance):
        return self.entry_class(self._request, instance)


    def _representation(self, entry_instances):
        entries = [self._entry_from_instance(instance)
                   for instance in entry_instances]

        want_full_representation = self._read_bool_parameter(
                'full_representations')
        if want_full_representation:
            self.entry_class.prepare_for_full_representation(entries)

        members = []
        for entry in entries:
            if want_full_representation:
                rep = entry.full_representation()
            else:
                rep = entry.short_representation()
            members.append(rep)

        rep = self.link()
        rep.update({'members': members})
        return rep


    def _read_bool_parameter(self, name):
        if name not in self._query_params:
            return False
        return (self._query_params[name].lower() == 'true')


    def _read_int_parameter(self, name, default):
        if name not in self._query_params:
            return default
        input_value = self._query_params[name]
        try:
            return int(input_value)
        except ValueError:
            raise exceptions.BadRequest('Invalid non-numeric value for %s: %r'
                                        % (name, input_value))


    def _apply_form_query(self, queryset):
        """Apply any query selectors passed as form variables."""
        for parameter, values in self._query_params.lists():
            if ':' in parameter:
                parameter, comparison_type = parameter.split(':', 1)
            else:
                comparison_type = None

            if not self._query_processor.has_selector(parameter):
                continue
            for value in values: # forms keys can have multiple values
                queryset = self._query_processor.apply_selector(
                        queryset, parameter, value,
                        comparison_type=comparison_type)
        return queryset


    def _filtered_queryset(self):
        return self._apply_form_query(self._fresh_queryset())


    def get(self):
        queryset = self._filtered_queryset()

        items_per_page = self._read_int_parameter('items_per_page',
                                                  self._DEFAULT_ITEMS_PER_PAGE)
        start_index = self._read_int_parameter('start_index', 0)
        page = queryset[start_index:(start_index + items_per_page)]

        rep = self._representation(page)
        rep.update({'total_results': len(queryset),
                    'start_index': start_index,
                    'items_per_page': items_per_page})
        return self._basic_response(rep)


    def full_representation(self):
        # careful, this rep can be huge for large collections
        return self._representation(self._fresh_queryset())


    def post(self):
        input_dict = self._decoded_input()
        try:
            instance = self.entry_class.create_instance(input_dict, self)
            entry = self._entry_from_instance(instance)
            entry.update(input_dict)
        except model_logic.ValidationError, exc:
            raise exceptions.BadRequest('Invalid input: %s' % exc)
        # RFC 2616 specifies that we provide the new URI in both the Location
        # header and the body
        response = http.HttpResponse(status=201, # Created
                                     content=entry.href())
        response['Location'] = entry.href()
        return response


class Relationship(Entry):
    _permitted_methods = ('GET', 'DELETE')

    # subclasses must override this with a dict mapping name to entry class
    related_classes = None


    def __init__(self, **kwargs):
        assert len(self.related_classes) == 2
        self.entries = dict((name, kwargs[name])
                            for name in self.related_classes)
        for name in self.related_classes: # sanity check
            assert isinstance(self.entries[name], self.related_classes[name])

        # just grab the request from one of the entries
        some_entry = self.entries.itervalues().next()
        super(Relationship, self).__init__(some_entry._request)


    @classmethod
    def from_uri_args(cls, request, **kwargs):
        # kwargs contains URI args for each entry
        entries = {}
        for name, entry_class in cls.related_classes.iteritems():
            entries[name] = entry_class.from_uri_args(request, **kwargs)
        return cls(**entries)


    def _uri_args(self):
        kwargs = {}
        for name, entry in self.entries.iteritems():
            kwargs.update(entry._uri_args())
        return kwargs


    def short_representation(self):
        rep = self.link()
        for name, entry in self.entries.iteritems():
            rep[name] = entry.short_representation()
        return rep


    @classmethod
    def _get_related_manager(cls, instance):
        """Get the related objects manager for the given instance.

        The instance must be one of the related classes.  This method will
        return the related manager from that instance to instances of the other
        related class.
        """
        this_model = type(instance)
        models = [entry_class.model for entry_class
                  in cls.related_classes.values()]
        if isinstance(instance, models[0]):
            this_model, other_model = models
        else:
            other_model, this_model = models

        _, field = this_model.objects.determine_relationship(other_model)
        this_models_fields = (this_model._meta.fields
                              + this_model._meta.many_to_many)
        if field in this_models_fields:
            manager_name = field.attname
        else:
            # related manager is on other_model, get name of reverse related
            # manager on this_model
            manager_name = field.related.get_accessor_name()

        return getattr(instance, manager_name)


    def _delete_entry(self):
        # choose order arbitrarily
        entry, other_entry = self.entries.itervalues()
        related_manager = self._get_related_manager(entry.instance)
        related_manager.remove(other_entry.instance)


    @classmethod
    def create_instance(cls, input_dict, containing_collection):
        other_name = containing_collection.unfixed_name
        cls._check_for_required_fields(input_dict, (other_name,))
        entry = containing_collection.fixed_entry
        other_entry = containing_collection.resolve_link(input_dict[other_name])
        related_manager = cls._get_related_manager(entry.instance)
        related_manager.add(other_entry.instance)
        return other_entry.instance


    def update(self, input_dict):
        pass


class RelationshipCollection(Collection):
    def __init__(self, request=None, fixed_entry=None):
        if request is None:
            request = fixed_entry._request
        super(RelationshipCollection, self).__init__(request)

        assert issubclass(self.entry_class, Relationship)
        self.related_classes = self.entry_class.related_classes
        self.fixed_name = None
        self.fixed_entry = None
        self.unfixed_name = None
        self.related_manager = None

        if fixed_entry is not None:
            self._set_fixed_entry(fixed_entry)
            entry_uri_arg = self.fixed_entry._uri_args().values()[0]
            self._query_params[self.fixed_name] = entry_uri_arg


    def _set_fixed_entry(self, entry):
        """Set the fixed entry for this collection.

        The entry must be an instance of one of the related entry classes.  This
        method must be called before a relationship is used.  It gets called
        either from the constructor (when collections are instantiated from
        other resource handling code) or from read_query_parameters() (when a
        request is made directly for the collection.
        """
        names = self.related_classes.keys()
        if isinstance(entry, self.related_classes[names[0]]):
            self.fixed_name, self.unfixed_name = names
        else:
            assert isinstance(entry, self.related_classes[names[1]])
            self.unfixed_name, self.fixed_name = names
        self.fixed_entry = entry
        self.unfixed_class = self.related_classes[self.unfixed_name]
        self.related_manager = self.entry_class._get_related_manager(
                entry.instance)


    def _query_parameters_accepted(self):
        return [(name, 'Show relationships for this %s' % entry_class.__name__)
                for name, entry_class
                in self.related_classes.iteritems()]


    def _resolve_query_param(self, name, uri_arg):
        entry_class = self.related_classes[name]
        return entry_class.from_uri_args(self._request, uri_arg)


    def read_query_parameters(self, query_params):
        super(RelationshipCollection, self).read_query_parameters(query_params)
        if not self._query_params:
            raise exceptions.BadRequest(
                    'You must specify one of the parameters %s and %s'
                    % tuple(self.related_classes.keys()))
        query_items = self._query_params.items()
        fixed_entry = self._resolve_query_param(*query_items[0])
        self._set_fixed_entry(fixed_entry)

        if len(query_items) > 1:
            other_fixed_entry = self._resolve_query_param(*query_items[1])
            self.related_manager = self.related_manager.filter(
                    pk=other_fixed_entry.instance.id)


    def _entry_from_instance(self, instance):
        unfixed_entry = self.unfixed_class(self._request, instance)
        entries = {self.fixed_name: self.fixed_entry,
                   self.unfixed_name: unfixed_entry}
        return self.entry_class(**entries)


    def _fresh_queryset(self):
        return self.related_manager.all()
