/*
Copyright (©) 2003-2023 Teus Benschop.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/


#include <setup/index.h>
#include <assets/view.h>
#include <assets/page.h>
#include <webserver/request.h>
#include <filter/roles.h>
#include <filter/string.h>
#include <filter/url.h>
#include <index/index.h>
#include <demo/logic.h>
#include <config/globals.h>
#include <database/config/general.h>
#include <setup/logic.h>
using namespace std;


// Returns a html page with a Bibledit splash screen.
// In case of $refresh, it refreshes to the home page.
string notice;
const char * setup_initialization_notice ()
{
  // Use http://base64online.org/encode/ to convert an image to inline graphic data.
  
  notice =
  "<!DOCTYPE html>\n"
  "<html>\n"
  "<head>\n"
  "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n"
  "<meta http-equiv=\"refresh\" content=\"2;URL=/index/index\" />\n"
  "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
  "<title>Setup</title>\n"
  "<style>\n"
  ".splash {\n"
  " height: 100%;\n"
  " width: 100%;\n"
  " background: radial-gradient(red, yellow, white);\n"
  " position: absolute;\n"
  " z-index: -1;\n"
  " opacity: 0.15;\n"
  "}\n"
  "img {\n"
  " min-height: 100%;\n"
  " min-width: 100%;\n"
  " height: 100%;\n"
  " width: 100%;\n"
  " position: absolute;\n"
  " top:-50%; bottom: -50%;\n"
  " left:-50%; right: -50%;\n"
  " margin: auto;\n"
  " z-index: -1;\n"
  " background-repeat: no-repeat;\n"
  " background-position: center center;\n"
  " background-size: contain;\n"
  "}\n"
  "</style>\n"
  "</head>\n"
  "<body>\n"
  "<div class=\"splash\"></div>\n"
  "<div><img src=\"data:image/svg+xml;base64,[encoded data, 13600 characters]\"></div>\n"
  "<div style=\"text-align: center;\">\n"
  "<h1>Setup</h1>\n"
  "<h2>... upgrading ...</h2>\n";
  // The above signature (... upgrading ...) is used elsewhere and should match with this for proper operation.

  // Visual progress indicator.
  // The progress bar restarts when it is near the end and the device is not yet ready initializing.
  // The user will understand that the device is still busy, and not think that it is not stuck.
  config_globals_setup_progress += 5;
  if (config_globals_setup_progress > 90) config_globals_setup_progress = 10;
  notice.append ("<p><progress value=\"" + filter::strings::convert_to_string (config_globals_setup_progress) + "\" max=\"100\"></progress></p>");
  
  // Informative text for progress indication.
  notice.append ("<p>... " + config_globals_setup_message + " ...</p>");
  
  // Remainder of the setup page.
  notice.append (
  "<p>Please sit back and keep the device on till the upgrade has completed.</p>\n"
  "</div>\n"
  "</body>\n"
  "</html>\n"
  );

  return notice.c_str();
}


string setup_index (void * webserver_request)
{
  Webserver_Request * request = static_cast<Webserver_Request *>(webserver_request);
  
  Assets_View view;

  // Get the existing Administrators.
  vector <string> admins = request->database_users ()->getAdministrators ();

  // Admins do not yet exist: Allow to enter an admin.
  if (admins.empty ()) {
    if (!request->post ["Submit"].empty ()) {
      string admin_username = request->post ["admin_username"];
      string admin_password = request->post ["admin_password"];
      string admin_email = request->post ["admin_email"];
      vector <string> errors;
      if (admin_username.length() < 5) errors.push_back ("Choose a longer username.");
      if (admin_password.length() < 7) errors.push_back ("Choose a longer password.");
      if (admin_email.length() < 5) errors.push_back ("Enter a valid email address.");
      if (errors.empty()) {
        // Store admin details.
        setup_set_admin_details (admin_username, admin_password, admin_email);
        setup_complete_gui ();
        // Store web site's base URL.
        string siteUrl = get_base_url (request);
        Database_Config_General::setSiteURL (siteUrl);
        // Redirect.
        redirect_browser (request, index_index_url ());
      } else {
        view.enable_zone ("errors");
        view.set_variable ("error", filter::strings::implode (errors, " "));
      }
    }
  }

  // Enable appropriate zones: Either enter admin's details, or else display the details.
  if (admins.empty ()) {
    view.enable_zone ("enteradmin");
    view.enable_zone ("enteruser");
    view.enable_zone ("enterpass");
    view.enable_zone ("entermail");
    view.enable_zone ("displaysubmit");
  } else {
    string usernames;
    string emails;
    for (unsigned int i = 0; i < admins.size(); i++) {
      if (i) {
        usernames.append (" / ");
        emails.append (" / ");
      }
      usernames.append (admins[i]);
      emails.append (request->database_users ()->get_email (admins[i]));
    }
    view.set_variable ("usernames", usernames);
    view.set_variable ("emails", emails);
    view.enable_zone ("displayok");
    view.set_variable ("readonly", "readonly");
    // If the admin's are already there, then the setup has completed.
    // The automatic page refresh will kick in, and navigate to the main screen.
    Database_Config_General::setInstalledInterfaceVersion (config::logic::version ());
  }

  return view.render ("setup", "index");
}


