<?php
declare(strict_types=1);
namespace MRBS;

use MRBS\Form\ElementFieldset;
use MRBS\Form\ElementInputSubmit;
use MRBS\Form\FieldDiv;
use MRBS\Form\FieldInputSubmit;
use MRBS\Form\FieldTextarea;
use MRBS\Form\Form;


require "defaultincludes.inc";
require_once "mrbs_sql.inc";
require_once "functions_view.inc";


function generate_registrant_table(array $row, ?string $previous_page=null) : void
{
  global $auth;

  echo "<div id=\"registrant_list\" class=\"datatable_container\">\n";
  echo "<table id=\"registrants\" class=\"admin_table display\">\n";

  echo "<thead>\n";
  echo '<tr>';
  echo '<th></th>';
  echo '<th class="name">' . get_vocab('name') . '</th>';
  echo '<th class="name">' . get_vocab('registered_by') . '</th>';
  echo '<th>' . get_vocab('registered_on') . '</th>';
  echo "</tr>\n";
  echo "</thead>\n";

  echo "<tbody>\n";

  $mrbs_user = session()->getCurrentUser();

  foreach ($row['registrants'] as $registrant)
  {
    echo '<tr>';
    echo '<td>';
    // A registration can be cancelled by the registrant or by
    // the person who registered them or by the booking owner or
    // if ordinary users are allowed to delete other users' registrations.
    if (getWritable($registrant['username'], $row['room_id']) ||
        getWritable($registrant['create_by'], $row['room_id']) ||
        getWritable($row['create_by'], $row['room_id']) ||
        (isset($mrbs_user) && $auth['users_can_delete_others_registrations']))
    {
      generate_cancel_registration_button(
        $row,
        $registrant,
        get_vocab('delete'),
        $previous_page
      );
    }
    echo '</td>';
    // Registrant and Registered by
    foreach(['username', 'create_by'] as $key)
    {
      // Default values
      $display_name = '';
      $email = null;
      // Only show a name if it's the registrant or the creator is someone other than the registrant
      if (($key != 'create_by') || ($registrant['create_by'] !== $registrant['username']))
      {
        if (can_see_email_addresses())
        {
          $user = auth()->getUser($registrant[$key]);
          if (isset($user))
          {
            $display_name = $user->display_name;
            $email = $user->email;
          }
          else
          {
            $display_name = $registrant[$key];
          }
        }
        else
        {
          // Can be faster sometimes if we don't need the email address
          $display_name = auth()->getDisplayName($registrant[$key]);
        }
      }
      $sort_name = get_sortable_name($display_name);
      echo '<td data-order="' . escape_html($sort_name) . '">';
      $display_name_html = escape_html($display_name);
      // Add a mailto: link if we've got an email address
      if (isset($email) && ($email !== ''))
      {
        $display_name_html = '<a href="mailto:' . escape_html($email) . '">' . $display_name_html . '</a>';
      }
      echo $display_name_html;
      echo '</td>';
    }
    // Time of registration
    $time = time_date_string($registrant['registered']);
    echo '<td data-order="' . intval($registrant['registered']) . '">' . escape_html($time) . '</td>';
    echo "</tr>\n";
  }

  echo "</tbody>\n";
  echo "</table>\n";
  echo "</div>\n";
}


function get_returl(?string $previous_page=null) : string
{
  global $server;

  static $returl=null;

  if (!isset($returl))
  {
    // Add the previous_page (ie the one we were on before view_entry) to the query string
    // so that it is preserved.
    $returl = this_page();
    $query_string = $server['QUERY_STRING'] ?? '';
    parse_str($query_string, $query_string_parts);
    if (isset($previous_page))
    {
      $query_string_parts['previous_page'] = $previous_page;
    }
    if (!empty($query_string_parts))
    {
      $returl .= '?' . http_build_query($query_string_parts, '', '&');
    }
  }

  return $returl;
}


function generate_cancel_registration_button(array $row, array $registrant, string $label_text, ?string $previous_page=null, bool $as_field=false) : void
{
  global $area, $room;

  // Check that it is not too late for ordinary users to cancel
  if (!getWritable($row['create_by'], $row['room_id']) && entry_registration_cancellation_has_closed($row))
  {
    return;
  }

  $form = new Form(Form::METHOD_POST);
  $form->setAttributes(array('action' => multisite('registration_handler.php')));

  if ($as_field)
  {
    $form->setAttribute('class', 'standard');
  }

  // Hidden inputs
  $form->addHiddenInputs(array(
    'action' => 'cancel',
    'registration_id' => $registrant['id'],
    'returl' => get_returl($previous_page),
    'area' => $area,
    'room' => $room
  ));

  // Submit button
  $button = new ElementInputSubmit();
  $display_name = auth()->getDisplayName($registrant['username']);
  $message = get_vocab("confirm_del_registrant", $display_name);
  $button->setAttributes(array(
      'value' => $label_text,
      'onclick' => "return confirm('" . escape_js($message) . "');"
    ));

  if ($as_field)
  {
    $fieldset = new ElementFieldset();
    $field = new FieldDiv();
    $field->addControl($button);
    $fieldset->addElement($field);
    $form->addElement($fieldset);
  }
  else
  {
    $form->addElement($button);
  }

  $form->render();
}


function generate_register_button(array $row, ?string $previous_page=null) : void
{
  global $area, $room;

  // Check that the user is an admin or else that the entry is open for registration
  if (!getWritable($row['create_by'], $row['room_id']) && !entry_registration_is_open($row))
  {
    return;
  }

  $mrbs_user = session()->getCurrentUser();
  $can_register_others = can_register_others($row['room_id']);

  $form = new Form(Form::METHOD_POST);
  $form->setAttributes(array('action' => multisite('registration_handler.php'),
                             'class'  => 'standard'));

  // Hidden inputs
  $form->addHiddenInputs(array(
      'action' => 'register',
      'event_id' => $row['id'],
      'returl' => get_returl($previous_page),
      'area' => $area,
      'room' => $room
    ));

  if (!$can_register_others)
  {
    $form->addHiddenInput('username', $mrbs_user->username);
  }
  else
  {
    $fieldset = new ElementFieldset();
    $params = array(
        'value'     => $mrbs_user->username,
        'disabled'  => false,
        'required'  => true,
        'field'     => 'participants.username',
        'label'     => get_vocab('name'),
        'name'      => 'username',
      );
    $fieldset->addElement(get_user_field($params, true));
    $form->addElement($fieldset);
  }

  // Submit button
  $fieldset = new ElementFieldset();
  $field = new FieldDiv();
  $element = new ElementInputSubmit();
  $element->setAttribute('value', get_vocab('register'));
  $field->addControl($element);
  $fieldset->addElement($field);
  $form->addElement($fieldset);

  $form->render();
}


function generate_event_registration(array $row, ?string $previous_page=null) : void
{
  global $auth;

  if (empty($row['allow_registration']))
  {
    return;
  }

  $can_register_others = can_register_others($row['room_id']);
  $can_see_others = $can_register_others || $auth['show_registrant_names'] || getWritable($row['create_by'], $row['room_id']);
  $n_registered = count($row['registrants']);


  echo '<h4>' . get_vocab('event_registration') . "</h4>\n";
  echo "<div id=\"registration\">\n";
  echo "<table class=\"list\">\n";
  echo "<tbody>\n";

  if ($row['registration_opens_enabled'])
  {
    echo '<tr>';
    echo '<td>' . escape_html(get_vocab('registration_opens')) . '</td>';
    echo '<td>' . escape_html(time_date_string(registration_opens_timestamp($row))) . '</td>';
    echo "</tr>\n";
  }

  if ($row['registration_closes_enabled'])
  {
    echo '<tr>';
    echo '<td>' . escape_html(get_vocab('registration_closes')) . '</td>';
    echo '<td>' . escape_html(time_date_string(registration_closes_timestamp($row))) . '</td>';
    echo "</tr>\n";
  }

  if (!empty($row['registrant_limit_enabled']))
  {
    echo '<tr>';
    echo '<td>' . escape_html(get_vocab('registrant_limit')) . '</td>';
    echo '<td>' . intval($row['registrant_limit']) . '</td>';  // Redundant escaping, just in case
    echo "</tr>\n";
  }

  echo '<tr>';
  echo '<td>' . escape_html(get_vocab('n_registered')) . '</td>';
  echo '<td>' . intval($n_registered) . '</td>';  // Redundant escaping, just in case
  echo "</tr>\n";
  echo "</tbody>\n";
  echo "</table>\n";

  // Display the list of registrants, if the user is allowed to see it, which is if
  // they have write access for this booking.
  // Display it as a table because in the future we might want to (a) add more columns,
  // eg date and time of registration and (b) use DataTables to make the list searchable
  // and exportable.
  if (($n_registered > 0) && $can_see_others)
  {
    generate_registrant_table($row, $previous_page);
  }

  // Display registration information and buttons for this user
  $mrbs_user = session()->getCurrentUser();
  // Doesn't make sense to have anonymous registration at the moment.
  // You'd have to have a different kind of registration form - and
  // also think about who is allowed to cancel.
  if (isset($mrbs_user) && ($mrbs_user->username !== ''))
  {
    if (!$can_register_others && in_arrayi($mrbs_user->username,
        array_column($row['registrants'], 'username')))
    {
      echo '<p>' . escape_html(get_vocab('already_registered')) . "</p>\n";
      foreach ($row['registrants'] as $registrant)
      {
        if (strcasecmp_locale($mrbs_user->username, $registrant['username']) === 0)
        {
          $this_registrant = $registrant;
          break;
        }
      }
      // If they can see others they'll have a delete button against their name.  Otherwise
      // we'll need to provide one for them.
      if (!$can_see_others)
      {
        generate_cancel_registration_button(
          $row,
          $this_registrant,
          get_vocab('cancel_registration'),
          $previous_page,
          true
        );
      }
    }
    else
    {
      if (empty($row['registrant_limit_enabled']) ||
          ($row['registrant_limit'] > $n_registered))
      {
        generate_register_button($row, $previous_page);
      }
      else
      {
        echo '<p>' . escape_html(get_vocab('event_full')) . "</p>\n";
      }
    }
  }

  echo "</div>\n";
}


// Generates a single button.  Parameters in the array $params
//
//    Mandatory parameters
//      action    The form action attribute
//      value     The value of the button
//      inputs    An array of hidden form inputs
//
//    Optional parameters
//      button_attributes   An array of attributes to be used for the button.
function generate_button(array $params, array $button_attributes=array()) : void
{
  // Note that until IE supports the form attribute on the button tag, we can't
  // use a <button> here and have to use the <input type="submit"> to create the
  // button.   This unfortunately means that styling options on the button are limited.

  $form = new Form(Form::METHOD_POST);

  $attributes = array('action' => $params['action']);

  $form->setAttributes($attributes);

  // Hidden inputs
  $form->addHiddenInputs($params['inputs']);

  // Submit button
  $element = new ElementInputSubmit();
  $element->setAttribute('value', $params['value'])
          ->setAttributes($button_attributes);
  $form->addElement($element);

  $form->render();
}


function generate_copy_buttons(int $id, ?int $repeat_id, bool $series, string $returl, bool $repeats_allowed) : void
{
  global $day, $month, $year;

  echo "<div>\n";

  if (!$series)
  {
    echo "<div>\n";
    $params = [
      'action' => multisite('edit_entry.php'),
      'value' => get_vocab('copyentry'),
      'inputs' => [
        'id' => $id,
        'copy' => true,
        'returl' => $returl
      ]
    ];
    generate_button($params);
    echo "</div>\n";
  }

  if ((!empty($repeat_id) || $series) && $repeats_allowed)
  {
    echo "<div>\n";
    $params = [
      'action' => multisite("edit_entry.php?day=$day&month=$month&year=$year"),
      'value' => get_vocab('copyseries'),
      'inputs' => [
        'id' => $id,
        'edit_series' => true,
        'copy' => true,
        'returl' => $returl
      ]
    ];
    generate_button($params);
    echo "</div>\n";
  }

  echo "</div>\n";
}


function generate_edit_and_delete_buttons(array $row, int $id, ?int $repeat_id, bool $series, string $returl, bool $repeats_allowed) : void
{
  global $day, $month, $year;

  // Check whether the entry is deletable (and therefore editable).  Also get the
  // reason.  We only get the first reason because it's easier just to display one
  // reason in a tooltip, rather than a complete list.  [Note: if the entry is
  // deletable but the series is not, the series button will not be disabled.  This
  // is something that needs to be fixed in the future.]
  $violations = mrbsCheckPolicy($row, null, null, true);

  if (empty($violations['errors']))
  {
    $button_attributes = [];
  }
  else
  {
    $button_attributes = [
      'disabled' => true,
      'title' => $violations['errors'][0]
    ];
  }

  // Edit and Edit Series
  echo "<div>\n";
  if (!$series)
  {
    echo "<div>\n";
    $params = [
      'action' => multisite('edit_entry.php'),
      'value' => get_vocab('editentry'),
      'inputs' => ['id' => $id, 'returl' => $returl]
    ];
    generate_button($params, $button_attributes);
    echo "</div>\n";
  }
  if ((!empty($repeat_id) || $series) && $repeats_allowed)
  {
    echo "<div>\n";
    $params = [
      'action' => multisite("edit_entry.php?day=$day&month=$month&year=$year"),
      'value' => get_vocab('editseries'),
      'inputs' => [
        'id' => $id,
        'edit_series' => true,
        'returl' => $returl
      ]
    ];

    if (empty($button_attributes['disabled']) &&
        isset($repeat_id) &&
        series_has_registrants($repeat_id))
    {
      $button_attributes['onclick'] = "return confirm('" . get_js_vocab("confirm_edit_series") . "');";
    }
    generate_button($params, $button_attributes);
    echo "</div>\n";
  }
  echo "</div>\n";

  // Delete and Delete Series
  echo "<div>\n";

  // For the delete buttons, either the button is disabled and we show the reason why, or else
  // we add a click event to confirm the deletion
  unset($button_attributes['onclick']);

  if (!$series)
  {
    echo "<div>\n";
    if (empty($button_attributes['disabled']))
    {
      $button_attributes['onclick'] = "return confirm('" . get_js_vocab('confirmdel') . "');";
    }
    $params = [
      'action' => multisite('del_entry.php'),
      'value' => get_vocab('deleteentry'),
      'inputs' => [
        'id' => $id,
        'series' => 0,
        'returl' => $returl
      ]
    ];
    generate_button($params, $button_attributes);
    echo "</div>\n";
  }

  if ((!empty($repeat_id) || $series) && $repeats_allowed)
  {
    echo "<div>\n";
    if (empty($button_attributes['disabled']))
    {
      $button_attributes['onclick'] = "return confirm('" . get_js_vocab('confirmdel_series') . "');";
    }
    $params = [
      'action' => multisite("del_entry.php?day=$day&month=$month&year=$year"),
      'value' => get_vocab('deleteseries'),
      'inputs' => [
        'id' => $id,
        'series' => 1,
        'returl' => $returl
      ]
    ];
    generate_button($params, $button_attributes);
    echo "</div>\n";
  }

  echo "</div>\n";
}


function generate_export_buttons(int $id, ?int $repeat_id, bool $series, string $returl) : void
{
  global $day, $month, $year;

  // The iCalendar information has the full booking details in it, so we will not allow
  // it to be exported if it is private and the user is not authorised to see it.
  // iCalendar information doesn't work with periods at the moment (no periods to times mapping)
  echo "<div>\n";

  if (!$series)
  {
    echo "<div>\n";
    $params = [
      'action' => multisite('view_entry.php'),
      'value' => get_vocab('exportentry'),
      'inputs' => [
        'id' => $id,
        'action' => 'export',
        'returl' => $returl
      ]
    ];
    generate_button($params);
    echo "</div>\n";
  }

  if (!empty($repeat_id) || $series)
  {
    echo "<div>\n";
    $params = [
      'action' => multisite("view_entry.php?day=$day&month=$month&year=$year"),
      'value' => get_vocab('exportseries'),
      'inputs' => [
        'id' => $repeat_id,
        'action' => 'export',
        'series' => 1,
        'returl' => $returl
      ]
    ];
    generate_button($params);
    echo "</div>\n";
  }

  echo "</div>\n";
}


// Generates the Approve, Reject and More Info buttons
function generateApproveButtons(int $id, bool $series) : void
{
  global $returl;
  global $entry_info_time, $entry_info_user, $repeat_info_time, $repeat_info_user;
  global $multisite, $site;

  $info_time = ($series) ? $repeat_info_time : $entry_info_time;
  $info_user = ($series) ? $repeat_info_user : $entry_info_user;

  $this_page = this_page();
  if (empty($info_time))
  {
    $info_title = get_vocab("no_request_yet");
  }
  else
  {
    $info_title = get_vocab("last_request") . ' ' . time_date_string($info_time);
    if (!empty($info_user))
    {
      $info_title .= " " . get_vocab("by") . " $info_user";
    }
  }

  $query_string = "id=$id&series=" . (($series) ? 1 : 0);
  if ($multisite && isset($site) && ($site !== ''))
  {
    $query_string .= "&site=$site";
  }

  echo "<tr>\n";
  echo "<td>" . ($series ? get_vocab("series") : get_vocab("entry")) . "</td>\n";
  echo "<td>\n";

  // Approve
  $params = array('action' => multisite("approve_entry_handler.php?$query_string"),
                  'value'  => get_vocab('approve'),
                  'inputs' => array('action' => 'approve',
                                    'returl' => $returl)
                 );
  generate_button($params);

  // Reject
  $params = array('action' => multisite("$this_page?$query_string"),
                  'value'  => get_vocab('reject'),
                  'inputs' => array('action' => 'reject',
                                    'returl' => $returl)
                 );
  generate_button($params);

  // More info
  $params = array('action' => multisite("$this_page?$query_string"),
                  'value'  => get_vocab('more_info'),
                  'inputs' => array('action' => 'more_info',
                                    'returl' => $returl)
                 );
  generate_button($params, array('title' => $info_title));

  echo "</td>\n";
  echo "</tr>\n";
}

function generateOwnerButtons(int $id, bool $series) : void
{
  global $mrbs_username, $create_by, $awaiting_approval, $area;
  global $reminders_enabled, $last_reminded, $reminder_interval;
  global $multisite, $site;

  // Remind button if you're the owner AND there's a booking awaiting
  // approval AND sufficient time has passed since the last reminder
  // AND we want reminders in the first place
  if ($reminders_enabled &&
      isset($mrbs_username) &&
      (strcasecmp_locale($mrbs_username, $create_by) === 0) &&
      $awaiting_approval &&
      (working_time_diff(time(), $last_reminded) >= $reminder_interval))
  {
    echo "<tr>\n";
    echo "<td class=\"no_suffix\"></td>\n";
    echo "<td>\n";

    $this_page = this_page();
    $returl = "$this_page?id=$id&area=$area";
    $query_string = "id=$id&series=" . (($series) ? 1 : 0);
    if ($multisite && isset($site) && ($site !== ''))
    {
      $query_string .= "&site=$site";
      $returl .= "&site=$site";
    }

    $params = array('action' => multisite("approve_entry_handler.php?$query_string"),
                    'value'  => get_vocab('remind_admin'),
                    'inputs' => array('action' => 'remind',
                                      'returl' => "$this_page?id=$id&area=$area")
                   );
    generate_button($params);

    echo "</td>\n";
    echo "</tr>\n";
  }
}

function generateTextArea(string $form_action, int $id, bool $series, string $action_type, string $returl, string $submit_value, string $caption, string $value='') : void
{
  echo "<tr><td id=\"caption\" colspan=\"2\">$caption</td></tr>\n";
  echo "<tr>\n";
  echo "<td id=\"note\" class=\"no_suffix\" colspan=\"2\">\n";

  $form = new Form(Form::METHOD_POST);

  $attributes = array('action' => $form_action);

  $form->setAttributes($attributes);

  // Hidden inputs
  $hidden_inputs = array('id'     => $id,
                         'series' => ($series) ? 1 : 0,
                         'returl' => $returl,
                         'action' => $action_type);
  $form->addHiddenInputs($hidden_inputs);

  // Visible fields
  $fieldset = new ElementFieldset();
  $fieldset->addLegend('');

  $field = new FieldTextarea();
  $field->setControlAttribute('name', 'note')
        ->setControlText($value);

  $fieldset->addElement($field);

  // The submit button
  $field = new FieldInputSubmit();
  $field->setControlAttribute('value', $submit_value);
  $fieldset->addElement($field);

  $form->addElement($fieldset);

  $form->render();

  echo "</td>\n";
  echo "<tr>\n";
}


// Get non-standard form variables
//
// If $series is TRUE, it means that the $id is the id of an
// entry in the repeat table.  Otherwise it's from the entry table.
$id = get_form_var('id', 'int');
$series = get_form_var('series', 'bool', false);
$action = get_form_var('action', 'string');
$returl = get_form_var('returl', 'string');
$error = get_form_var('error', 'string');
$previous_page = get_form_var('previous_page', 'string');

$referrer = session()->getReferrer();

if (!isset($previous_page) && isset($referrer))
{
  $previous_page = $referrer;
}

// Need to tell all the links where to go back to after an edit or delete
if (!isset($returl))
{
  // We need $referrer to contain an actual page, and not be a directory, ie end in '/'
  if (isset($referrer) && (substr($referrer, -1) != '/'))
  {
    $parsed_url = parse_url($referrer);
    if (isset($parsed_url['path']))
    {
      $returl = basename($parsed_url['path']);
    }
  }
  // If we still haven't got a referrer (eg if we've come here from an email) then construct
  // a sensible place to go to afterwards
  if (!isset($returl))
  {
    $returl = 'index.php';
  }

  // Add on the query string
  if (isset($parsed_url['query']))
  {
    $returl .= '?' . $parsed_url['query'];
  }
  else
  {
    $vars = array('view'  => $default_view,
                  'year'  => $year,
                  'month' => $month,
                  'day'   => $day,
                  'area'  => $area,
                  'room'  => $room);

    $returl .= '?' . http_build_query($vars, '', '&');
  }
}

// Check the CSRF token if we're going to do something
if (isset($action))
{
  Form::checkToken();
}

// Check the user is authorised for this page
checkAuthorised(this_page());

$mrbs_user = session()->getCurrentUser();
$mrbs_username = (isset($mrbs_user)) ? $mrbs_user->username : null;

// You're only allowed to make repeat bookings if you're an admin
// or else if $auth['only_admin_can_book_repeat'] is not set
$repeats_allowed = is_book_admin() || empty($auth['only_admin_can_book_repeat']);

$row = get_booking_info($id, $series);

$room = $row['room_id'];
$area = $row['area_id'];

// Get the area settings for the entry's area.   In particular we want
// to know how to display private/public bookings in this area.
get_area_settings($row['area_id']);

// Work out whether the room or area is disabled
$room_disabled = $row['room_disabled'] || $row['area_disabled'];
// Get the approval status
$awaiting_approval = $row['awaiting_approval'];
// Work out whether this event should be kept private
$private = $row['private'];
// Get the creator
$create_by = $row['create_by'];
$writeable = getWritable($row['create_by'], $row['room_id']);
$keep_private = (is_private_event($private) && !$writeable);

// Work out when the last reminder was sent
$last_reminded = (empty($row['reminded'])) ? $row['last_updated'] : $row['reminded'];


if ($series)
{
  $repeat_id = $id;  // Save the repeat_id
  // I also need to set $id to the value of a single entry as it is a
  // single entry from a series that is used by del_entry.php and
  // edit_entry.php
  // So I will look for the first entry in the series where the entry is
  // as per the original series settings
  $sql = "SELECT id
          FROM " . _tbl('entry') . "
          WHERE repeat_id=? AND entry_type=" . ENTRY_RPT_ORIGINAL . "
          ORDER BY start_time
          LIMIT 1";
  $id = db()->query1($sql, array($id));
  if ($id < 1)
  {
    // if all entries in series have been modified then
    // as a fallback position just select the first entry
    // in the series
    // hopefully this code will never be reached as
    // this page will display the start time of the series
    // but edit_entry.php will display the start time of the entry
    $sql = "SELECT id
            FROM " . _tbl('entry') . "
            WHERE repeat_id=?
            ORDER BY start_time
            LIMIT 1";
    $id = db()->query1($sql, array($id));
  }
  $repeat_info_time = $row['repeat_info_time'];
  $repeat_info_user = $row['repeat_info_user'];
  $repeat_info_text = $row['repeat_info_text'];
}
else
{
  $repeat_id = $row['repeat_id'];

  $entry_info_time = $row['entry_info_time'];
  $entry_info_user = $row['entry_info_user'];
  $entry_info_text = $row['entry_info_text'];
}


// PHASE 2 - EXPORTING ICALENDAR FILES
// -------------------------------------

if (isset($action) && ($action == "export"))
{
  if ($keep_private  || $enable_periods)
  {
    // should never normally be able to get here, but if we have then
    // go somewhere safe.
    location_header('index.php');
  }
  else
  {
    // Construct the SQL query
    $sql_params = array();
    $sql = "SELECT E.*, "
         .  db()->syntax_timestamp_to_unix("E.timestamp") . " AS last_updated, "
         . "A.area_name, R.room_name, "
         . "A.approval_enabled, A.confirmation_enabled";
    if ($series)
    {
      // If it's a series we want the repeat information
      $sql .= ", T.rep_type, T.end_date, T.rep_opt, T.rep_interval, T.month_absolute, T.month_relative";
    }
    $sql .= " FROM " . _tbl('area') . " A, " . _tbl('room') . " R, " . _tbl('entry') . " E";
    if ($series)
    {
      $sql .= ", " . _tbl('repeat') . " T"
            . " WHERE E.repeat_id=?"
            . " AND E.repeat_id=T.id";
      $sql_params[] = $repeat_id;
    }
    else
    {
      $sql .= " WHERE E.id=?";
      $sql_params[] = $id;
    }

    $sql .= " AND E.room_id=R.id
              AND R.area_id=A.id";

    if ($series)
    {
      $sql .= " ORDER BY E.start_time";
    }
    $res = db()->query($sql, $sql_params);

    // Export the calendar
    require_once "functions_ical.inc";

    $content_type = "application/ics;  charset=" . get_charset(). "; name=\"" . $mail_settings['ics_filename'] . ".ics\"";
    $content_disposition = "attachment; filename=\"" . $mail_settings['ics_filename'] . ".ics\"";
    http_headers(array("Content-Type: $content_type",
                       "Content-Disposition: $content_disposition"));

    export_icalendar($res, $keep_private);
    exit;
  }
}

// PHASE 1 - VIEW THE ENTRY
// ------------------------

$context = array(
    'view'      => $view,
    'view_all'  => $view_all,
    'year'      => $year,
    'month'     => $month,
    'day'       => $day,
    'area'      => $area,
    'room'      => $room ?? null
  );

print_header($context);

// Now that we know all the data we start drawing it

echo "<h3" . (($keep_private && $is_private_field['entry.name']) ? " class=\"private\"" : "") . ">\n";
echo ($keep_private && $is_private_field['entry.name']) ? get_vocab("unavailable") : escape_html($row['name']);
if (is_private_event($private) && $writeable)
{
  echo ' ' . get_vocab("unavailable");
}
echo "</h3>\n";

generate_event_registration($row, $previous_page);

echo '<h4>' . get_vocab('event_details') . "</h4>\n";

echo "<table id=\"entry\" class=\"list\">\n";

// Output any error messages
if (!empty($error))
{
  echo "<tr><td>&nbsp;</td><td class=\"error\">" . get_vocab($error) . "</td></tr>\n";
}

// If it's a registration event, then we only show the most important details, unless it's writable.
$major_details_only = $row['allow_registration'] && !getWritable($row['create_by'], $row['room_id'], false);
echo create_details_body($row, true, $keep_private, $room_disabled, $major_details_only);

// If bookings require approval, and the room is enabled, put the buttons
// to do with managing the bookings in the footer
if ($approval_enabled && !$room_disabled && $awaiting_approval)
{
  echo "<tfoot id=\"approve_buttons\">\n";
  // PHASE 2 - REJECT
  if (isset($action) && ($action == "reject"))
  {
    // del_entry expects the id of a member of a series
    // when deleting a series and not the repeat_id
    generateTextArea(multisite('del_entry.php'), $id, $series,
                     "reject", $returl,
                     get_vocab("reject"),
                     get_vocab("reject_reason"));
  }
  // PHASE 2 - MORE INFO
  elseif (isset($action) && ($action == "more_info"))
  {
    // but approve_entry_handler expects the id to be a repeat_id
    // if $series is true (ie behaves like the rest of MRBS).
    // Sometime this difference in behaviour should be rationalised
    // because it is very confusing!
    $target_id = ($series) ? $repeat_id : $id;
    $info_time = ($series) ? $repeat_info_time : $entry_info_time;
    $info_user = ($series) ? $repeat_info_user : $entry_info_user;
    $info_text = ($series) ? $repeat_info_text : $entry_info_text;

    if (empty($info_time))
    {
      $value = '';
    }
    else
    {
      $value = get_vocab("sent_at") . time_date_string($info_time);
      if (!empty($info_user))
      {
        $value .= "\n" . get_vocab("by") . " $info_user";
      }
      $value .= "\n----\n";
      $value .= $info_text;
    }
    generateTextArea(multisite('approve_entry_handler.php'), $target_id, $series,
                     "more_info", $returl,
                     get_vocab("send"),
                     get_vocab("request_more_info"),
                     $value);
  }
  // PHASE 1 - first time through this page
  else
  {
    // Buttons for those who are allowed to approve this booking
    if (is_book_admin($row['room_id']))
    {
      if (!$series)
      {
        generateApproveButtons($id, false);
      }
      if (!empty($repeat_id) || $series)
      {
        generateApproveButtons($repeat_id, true);
      }
    }
    // Buttons for the owner of this booking
    elseif (isset($mrbs_username) && strcasecmp_locale($mrbs_username, $create_by) === 0)
    {
      generateOwnerButtons($id, $series);
    }
    // Others don't get any buttons
  }
  echo "</tfoot>\n";
}
echo "</table>\n";

echo "<div id=\"view_entry_nav\">\n";

// Set the return URL.  If $previous_page is set and $returl is not 'index.php' then
// it means that we've come from the registration handler and the original return URL
// is held in $previous_page.
// TODO: simplify the code concerning return urls, target urls and the previous page
// TODO: throughout MRBS.

if (isset($previous_page) &&
    (!(isset($returl) && (basename(parse_url($returl)['path']) == 'index.php'))))
{
  $returl = $previous_page;
}

if (!$major_details_only)
{
  // Only show the links for Edit and Delete if (a) the room is enabled, and (b) the user
  // is allowed to use them.  (We're allowed to view and copy existing bookings in disabled
  // rooms, but not to modify or delete them.)
  if (!$room_disabled && getWritable($create_by, $room))
  {
    generate_edit_and_delete_buttons($row, $id, $repeat_id, $series, $returl, $repeats_allowed);
  }

  // Copy and Copy Series
  if (!$auth['only_admin_can_copy_others_entries'] || $writeable)
  {
    generate_copy_buttons($id, $repeat_id, $series, $returl, $repeats_allowed);
  }

  // Export and Export Series
  if (!$keep_private && !$enable_periods)
  {
    generate_export_buttons($id, $repeat_id, $series, $returl);
  }
}

echo "</div>\n";  // id="view_entry_nav"

// Don't display a link to the previous page if there isn't one (eg if we've got here
// from an email), or if it would just send the user to the same page for some reason.
if (isset($previous_page) &&
    (basename(parse_url($previous_page)['path']) !== this_page()))
{
  echo "<div id=\"returl\">\n";
  echo '<a href="' . escape_html($previous_page) . '">' . get_vocab('returnprev') . "</a>\n";
  echo "</div>\n";
}


print_footer();
