public function calculate(array &$data)
    {
        $result = array();
        $this->hook->attach('order.calculate.before', $data, $result, $this);

        if (!empty($result)) {
            return (array) $result;
        }

        $components = array();
        $total = $data['cart']['total'];

        $this->calculateComponents($total, $data, $components);
        $this->calculatePriceRules($total, $data, $components);

        $result = array(
            'total' => $total,
            'components' => $components,
            'currency' => $data['cart']['currency'],
            'total_decimal' => $this->price->decimal($total, $data['cart']['currency']),
            'total_formatted' => $this->price->format($total, $data['cart']['currency']),
            'total_formatted_number' => $this->price->format($total, $data['cart']['currency'], true, false),
        );

        $this->hook->attach('order.calculate.after', $data, $result, $this);
        return (array) $result;
    }