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