# Path: depot/helpers.py
# def get_depot_if_allowed(depot_id, user):
#     """
#     Return the depot for the given if the user is allowed to access it
# 
#     Otherwise throws a PermissionDenied exception.
# 
#     :author: Benedikt Seidl
#     """
# 
#     depot = get_object_or_404(Depot, pk=depot_id)
# 
#     if not depot.organization.managed_by(user) and not depot.active:
#         raise PermissionDenied('Depot is not active')
# 
#     return depot
# 
# def extract_item_quantities(data):
#     """
#     Extract the item quantities from the provided dictionary
# 
#     The format matches the input names of the rental creation form.
#     Only positive quantities are considered.
# 
#     :author: Benedikt Seidl
#     """
# 
#     item_quantities = {}
#     for key, quantity in data.items():
#         m = re.match(r'^item-([0-9]+)-quantity$', key)
#         if m is not None and int(quantity) > 0:
#             item_quantities[int(m.group(1))] = int(quantity)
# 
#     return item_quantities
# 
# Path: rental/availability.py
# class Availability:
#     """
#     Helper class to determine the availability of a list of items
# 
#     An item becomes only unavailable when it is parted of an approved rental
#     request. All other items, especially in rental requests that are still
#     pending, are considered available.
# 
#     :author: Leo Tappe
#     """
# 
#     def __init__(self, start_date, return_date, depot_id,
#                  conflicting_states=[Rental.STATE_APPROVED]):
#         self.start_date = start_date
#         self.return_date = return_date
#         self.depot_id = depot_id
#         self.conflicting_states = conflicting_states
# 
#     def get_availability_intervals(self, item):
#         """
#         Split the given time frame into a sequence of intervals
#         with the corresponding amount of available elements.
# 
#         :author: Leo Tappe
# 
#         :param item: the item that you want to rent
#         :return: a list of lists of the form [from, to, num_available]
#         """
# 
#         interval_borders = []
#         intervals = []
# 
#         rentals = Rental.objects.filter(
#             start_date__lt=self.return_date,
#             return_date__gt=self.start_date,
#             depot_id=self.depot_id,
#             state__in=self.conflicting_states,
#             items=item
#         ).prefetch_related(
#             Prefetch(
#                 'itemrental_set',
#                 queryset=ItemRental.objects.filter(item=item),
#                 to_attr='relevant_rental'
#             )
#         )
# 
#         # collect all the datetimes where a relevant rental starts / gets returned
#         for rental in rentals:
#             if rental.start_date > self.start_date:
#                 interval_borders.append(rental.start_date)
#             if rental.return_date < self.return_date:
#                 interval_borders.append(rental.return_date)
# 
#         # insert start and end date
#         interval_borders.append(self.start_date)
#         interval_borders.append(self.return_date)
# 
#         # sort these points
#         interval_borders.sort()
# 
#         # create intervals, initialize with full availability
#         for begin, end in zip(interval_borders, interval_borders[1:]):
#             intervals.append(Interval(begin, end, item.quantity))
# 
#         # for each rental, modify availability during occupied intervals accordingly
#         for rental in rentals:
#             for interval in intervals:
#                 if rental.start_date < interval.end and rental.return_date > interval.begin:
#                     interval.value -= rental.relevant_rental[0].quantity
# 
#         return intervals


from datetime import datetime, timedelta
from depot.helpers import get_depot_if_allowed, extract_item_quantities
from django.shortcuts import render
from django.views import View
from rental.availability import Availability
        start_date, return_date = self.get_start_return_date(request.GET)

        item_list = depot.visible_items(request.user)

        availability = Availability(
            datetime.combine(start_date.date() - timedelta(days=1), datetime.min.time()),
            datetime.combine(return_date.date() + timedelta(days=1), datetime.min.time()),
            depot_id
        )

        availability_data = []

        for item in item_list:
            intervals = availability.get_availability_intervals(item)

            availability_data.append((
                item,
                self.get_chart_data(intervals),
                min(intervals).value
            ))

        errors = request.session.pop('errors', None)
        data = request.session.pop('data', {})

        return render(request, 'depot/create-rental.html', {
            'depot': depot,
            'show_visibility': depot.show_internal_items(request.user),
            'availability_data': availability_data,
            'errors': errors,
            'data': data,

# Path: depot/helpers.py
# def get_depot_if_allowed(depot_id, user):
#     """
#     Return the depot for the given if the user is allowed to access it
# 
#     Otherwise throws a PermissionDenied exception.
# 
#     :author: Benedikt Seidl
#     """
# 
#     depot = get_object_or_404(Depot, pk=depot_id)
# 
#     if not depot.organization.managed_by(user) and not depot.active:
#         raise PermissionDenied('Depot is not active')
# 
#     return depot
# 
# def extract_item_quantities(data):
#     """
#     Extract the item quantities from the provided dictionary
# 
#     The format matches the input names of the rental creation form.
#     Only positive quantities are considered.
# 
#     :author: Benedikt Seidl
#     """
# 
#     item_quantities = {}
#     for key, quantity in data.items():
#         m = re.match(r'^item-([0-9]+)-quantity$', key)
#         if m is not None and int(quantity) > 0:
#             item_quantities[int(m.group(1))] = int(quantity)
# 
#     return item_quantities
# 
# Path: rental/availability.py
# class Availability:
#     """
#     Helper class to determine the availability of a list of items
# 
#     An item becomes only unavailable when it is parted of an approved rental
#     request. All other items, especially in rental requests that are still
#     pending, are considered available.
# 
#     :author: Leo Tappe
#     """
# 
#     def __init__(self, start_date, return_date, depot_id,
#                  conflicting_states=[Rental.STATE_APPROVED]):
#         self.start_date = start_date
#         self.return_date = return_date
#         self.depot_id = depot_id
#         self.conflicting_states = conflicting_states
# 
#     def get_availability_intervals(self, item):
#         """
#         Split the given time frame into a sequence of intervals
#         with the corresponding amount of available elements.
# 
#         :author: Leo Tappe
# 
#         :param item: the item that you want to rent
#         :return: a list of lists of the form [from, to, num_available]
#         """
# 
#         interval_borders = []
#         intervals = []
# 
#         rentals = Rental.objects.filter(
#             start_date__lt=self.return_date,
#             return_date__gt=self.start_date,
#             depot_id=self.depot_id,
#             state__in=self.conflicting_states,
#             items=item
#         ).prefetch_related(
#             Prefetch(
#                 'itemrental_set',
#                 queryset=ItemRental.objects.filter(item=item),
#                 to_attr='relevant_rental'
#             )
#         )
# 
#         # collect all the datetimes where a relevant rental starts / gets returned
#         for rental in rentals:
#             if rental.start_date > self.start_date:
#                 interval_borders.append(rental.start_date)
#             if rental.return_date < self.return_date:
#                 interval_borders.append(rental.return_date)
# 
#         # insert start and end date
#         interval_borders.append(self.start_date)
#         interval_borders.append(self.return_date)
# 
#         # sort these points
#         interval_borders.sort()
# 
#         # create intervals, initialize with full availability
#         for begin, end in zip(interval_borders, interval_borders[1:]):
#             intervals.append(Interval(begin, end, item.quantity))
# 
#         # for each rental, modify availability during occupied intervals accordingly
#         for rental in rentals:
#             for interval in intervals:
#                 if rental.start_date < interval.end and rental.return_date > interval.begin:
#                     interval.value -= rental.relevant_rental[0].quantity
# 
#         return intervals


# Path: depot/views/depot_create_rental_view.py
from datetime import datetime, timedelta
from depot.helpers import get_depot_if_allowed, extract_item_quantities
from django.shortcuts import render
from django.views import View
from rental.availability import Availability

        start_date, return_date = self.get_start_return_date(request.GET)

        item_list = depot.visible_items(request.user)

        availability = Availability(
            datetime.combine(start_date.date() - timedelta(days=1), datetime.min.time()),
            datetime.combine(return_date.date() + timedelta(days=1), datetime.min.time()),
            depot_id
        )

        availability_data = []

        for item in item_list:
            intervals = availability.get_availability_intervals(item)

            availability_data.append((
                item,
                self.get_chart_data(intervals),
                min(intervals).value
            ))

        errors = request.session.pop('errors', None)
        data = request.session.pop('data', {})

        return render(request, 'depot/create-rental.html', {
            'depot': depot,
            'show_visibility': depot.show_internal_items(request.user),
            'availability_data': availability_data,
            'errors': errors,
            'data': data,

            'item_quantities': extract_item_quantities(data),