def get(self):
        """ Gets all events that have been created.

        URL Args:
            category (str): The category you want the events for. If category
                is 'all', then this will return all events. Any sub_categories
                will also be queried for events.
        """
        category = request.args.get("category", "all")
        if category == 'all':
            events = Event.query(ancestor=Event.root_key())
        else:
            category = PointCategory.get_from_name(category)
            if category is None:
                response = jsonify(message="Category does not exist")
                response.status_code = 404
                return response

            keys = []
            keys.append(category.key)
            keys.extend(category.sub_categories)

            events = Event.query(Event.point_category.IN(keys), ancestor=Event.root_key())

        events = events.order(Event.date)

        out = {'events': []}
        for event in events:
            out['events'].append({
                "name": event.name,
                "date": event.date.strftime('%m/%d/%Y'),
                "point-category": event.point_category.get().name,
            })

        return jsonify(**out)
    def post(self):
        """ Creates a new event. """
        data = request.form

        # Don't allow duplicate events
        event = Event.get_from_name(data['name'])
        if event is not None:
            response = jsonify(message="Duplicate resource")
            response.status_code = 409
            return response

        # Get the point category by name
        point_category = PointCategory.get_from_name(data['point-category'])
        if point_category is None:
            raise Exception("Unknonwn point category: " + data['point-category'])

        new_event = Event(parent=Event.root_key())
        new_event.date = datetime.strptime(data['date'], "%Y-%m-%d")
        new_event.name = data['name']
        new_event.point_category = point_category.key
        new_event.put()

        # Make sure there are point records for this event
        new_event.populate_records()

        response = jsonify()
        response.status_code = 201
        response.headers['location'] = "/api/events/" + new_event.name.replace(" ", "")
        return response
    def delete(self, name):
        category = PointCategory.get_from_name(name)
        if category is None:
            response = jsonify(message="Resource does not exist")
            response.status_code = 404
            return response

        category.key.delete();
    def get(self, name):
        category = PointCategory.get_from_name(name)
        if category is None:
            response = jsonify(message="Resource does not exist")
            response.status_code = 404
            return response

        sub_categories = []
        for cat in category.sub_categories:
            sub_categories.append(cat.get().name)

        data = {
            "sub_categories": sub_categories,
            "name": category.name,
        }
        return jsonify(**data)
    def post(self):
        """ Creates a new point category or updates a duplicate one

        If this function is given a point category with the same name as one
        that already exists, it will update the existing point category. It
        handles removing and adding necessary keys of parent categories.
        """
        data = request.form
        new_category = None
        new_key = None

        # TODO (phillip): we shouldn't put anything in the datastore if there is an error.
        # Therefore, we should wait until the end of the function to call a
        # put if possible.

        # Check to see if the category already exists
        for category in PointCategory.query():
            if category.name == data['name']:
                new_category = category
                new_key = new_category.key

                parent = new_category.parent
                if parent is not None:
                    # Update old parent sub categories
                    parent.sub_categories.remove(new_key)
                    parent.put()

        # If the category doesn't exist, create a new one
        if not new_category:
            new_category = PointCategory(parent=PointCategory.root_key())
            new_category.name = data['name']
            new_key = new_category.put()

        # If necessary, add the proper key to the parent category
        parent = data.get('parent', None)
        # TODO (phillip): Should I really also be checking for "none"? Is there a
        # better way?
        if parent is not None and parent != "none":
            parent = PointCategory.get_from_name(parent)
            parent.sub_categories.append(new_key)
            parent.put()

        response = jsonify()
        response.status_code = 201
        response.headers['location'] = "/api/point-categories/" + new_category.name.replace(" ", "")
        return response
    def patch(self, name):
        data = request.form
        baby_requirement = data.get('baby_requirement', None)
        member_requirement = data.get('member_requirement', None)

        category = PointCategory.get_from_name(name)
        if baby_requirement is not None:
            category.baby_requirement = int(baby_requirement)

        if member_requirement is not None:
            category.member_requirement = int(member_requirement)
        category.put()

        # TODO (phillip): A put request (and really any other request that creates or
        # updates an object) should return the new representation of that
        # object so clients don't need to make more API calls

        response = jsonify()
        response.status_code = 204
        return response
    def put(self, event):
        data = request.form

        new_event_name = data['name']
        dup_event = Event.get_from_name(new_event_name)
        # Don't allow duplicate events
        if dup_event is not None and new_event_name.replace(" ", "") != event.replace(" ", ""):
            response = jsonify(message="Duplicate resource")
            response.status_code = 409
            return response

        event = Event.get_from_name(event)
        if event is None:
            # TODO (phillip): this code is duplicated, maybe make some sort of default
            # handler that can be called for any resource that doesn't exist?
            response = jsonify(message="Resource does not exist")
            response.status_code = 404
            return response

        # Get the point category by name
        point_category = PointCategory.get_from_name(data['point-category'])
        if point_category is None:
            raise Exception("Unknonwn point category: " + data['point-category'])

        records = PointRecord.query(PointRecord.event_name == event.name)
        for record in records:
            record.event_name = data['name']
            record.put()

        event.name = data['name']
        event.date = datetime.strptime(data['date'], "%Y-%m-%d")
        event.point_category = point_category.key
        event.put()

        response = jsonify()
        response.status_code = 201
        response.headers['location'] = "/api/events/" + event.name.replace(" ", "")
        return response