def process_request(self, req):
        """Collect the data needed for a burndown chart and pass to JavaScript. 
        If the original request was via AJAX we use to_json, otherwise
        we return data via add_script_data.

        Remember that our data reflects how a project looked at the end of a 
        day - so if the ticket_bi_historical table has 20 opens tickets on 
        the 1st December, that were 20 open tickets at the end of that day.
        """

        # Get milestone object and all child milestones
        # we already know it exists, as we checked in the match_request()
        milestone = Milestone(self.env, req.args['id'])
        tree = Milestone.build_tree(self.env)
        all_milestones = [m.name for m in tree.find(milestone.name).traverse()]

        # If anyone request burndownchart/milestone_id not via AJAX
        # and not with a format argument (eg when printing) , we redirect to 
        # milestone/milestonename, as we need to load pre_process_request first
        XMLHttp = req.get_header('X-Requested-With') == 'XMLHttpRequest'
        if not XMLHttp and 'format' not in req.args:
            req.redirect(req.href.milestone(milestone.name))

        # Calculate series of dates used to render the burn down charts
        start = self.get_start_date(req, milestone)
        end = self.get_end_date(milestone)
        day_before_start = start - timedelta(days=1)
        dates = self.dates_inbetween(day_before_start, end)

        # Open a database connection
        self.log.debug('Connecting to the database to retrieve chart data')
        db = self.env.get_read_db()

        # If no metric data is posted, use the project default self.unit_value
        metric = req.args.get('metric', self.unit_value)

        # Remaining Effort (aka burndown) Curve
        remaining_effort_args = [db, all_milestones, day_before_start, end]

        burndown_series = []
        if metric == 'tickets':
            burndown_series = self.tickets_open_between_dates(*remaining_effort_args)
        elif metric == 'hours':
            burndown_series = self.hours_remaining_between_dates(*remaining_effort_args)
        elif metric == 'points':
            burndown_series = self.points_remaining_between_dates(*remaining_effort_args)

        # If we don't have any burndown data send a message and stop
        if not burndown_series:
            data = {'result': False}
            # For ajax request
            if XMLHttp:
                req.send(to_json(data), 'text/json')
            else:
                return 'burndown_print.html', data, None

        # Team Effort Curve
        team_effort = self.team_effort_curve(db, metric, all_milestones,
                                                day_before_start, end,
                                                self.dates_as_strings(dates))

        # Ideal Curve (unit value doesnt matter)
        if self.ideal_value == 'fixed':
            original_estimate = burndown_series[0][1]

        ideal_data = self.ideal_curve(original_estimate, day_before_start, 
                                      self.get_due_date(milestone))

        data = {
            'burndowndata': burndown_series,
            'teameffortdata' : team_effort,
            'idealcurvedata': ideal_data,
            'milestone_name': milestone.name,
            'start_date': str(day_before_start),
            'effort_units': metric,
            'yaxix_label': metric.title(),
            'result' : True,
        }

        # we need some logic to work out the end date on the xAxis
        data['due_date'] =  (self.get_due_date(milestone)).strftime("%Y-%m-%d")

        # Ajax request
        if XMLHttp:
            kwargs = { 'daysback':0,
                       'ticket':'on',
                       'ticket_details': 'on',
                       'ticket_milestone_%s' % Milestone._hash_name(milestone.name): 'on'
                     }
            data.update({
              'timeline_url': req.href.timeline(kwargs),
              'print_burndown': False,
              'render_burndown': True,
            })

            req.send(to_json(data), 'text/json')

        # Normal request (eg the print friendly page)
        else:
            if req.args.get('format') == 'print':
                # Load the burn down JS file and jqPlot library 
                add_script(req, 'burndown/js/burndown.js')
                self._add_static_files(req)

                result = {'data': data,
                          'print_burndown': True,
                          'render_burndown': True,
                          'result': True,
                         }

                add_script_data(req, result)
                return 'burndown_print.html', result, None