<?php

// =============
// Reports Class
// =============

class Reports extends Base {

    // Variables.

    private $current_user_id = "";
    private $current_user_name = "";
    private $current_user_email = "";
    private $pagination_size = 20;
    private $pagination_page = 1;

    // =================
    // Class Constructor
    // =================

    public function __construct() {

        set_error_handler(array($this, "displayError"));

        date_default_timezone_set(self::TIMEZONE);

        $this->current_user_id = $_SESSION[self::USER_ID] ?? "";
        $this->current_user_name = $_SESSION[self::USER_NAME] ?? "";
        $this->current_user_email = $_SESSION[self::USER_EMAIL] ?? "";

        $this->pagination_page = $_SESSION[self::PAGINATION_PAGE] ?? 1;
    }

    // ==========
    // Add Report
    // ==========

    public function addReport() {

        $step = filter_input(INPUT_POST, "step") ?: "prompt";

        switch ($step) {

            case "prompt":

                $constants = $this->getConstants();

                $XML = $this->mergeXML($constants, "<XML/>");

                $content = $this->applyXSL($XML, $this->getXSL("addReport"));

                $this->displayContent($content);

                break;

            case "add":

                $report_name = filter_input(INPUT_POST, "report_name") ?: "";
                $report_class = filter_input(INPUT_POST, "report_class") ?: "";
                $report_type = filter_input(INPUT_POST, "report_type") ?: "Report";
                $report_description = filter_input(INPUT_POST, "report_description") ?: "";
                $report_target = filter_input(INPUT_POST, "report_target") ?: "";

                $report_class = trim(preg_replace("/\s+/", " ", $report_class));

                $SQL = "insert into reports
          
                         (  report_class,
                            report_type,
                            report_name,
                            report_description,
                            report_target )

                  VALUES ( :report_class,
                           :report_type,
                           :report_name,
                           :report_description,
                           :report_target)";

                $statement = $this->connect()->prepare($SQL);

                $statement->bindValue(":report_class", $report_class);
                $statement->bindValue(":report_type", $report_type);
                $statement->bindValue(":report_name", $report_name);
                $statement->bindValue(":report_description", $report_description);
                $statement->bindValue(":report_target", $report_target);

                $statement->execute();

                break;

            default:

                $this->displayHome();
        }
    }

    // =============
    // Delete Report
    // =============

    public function deleteReport() {

        $report_serial = filter_input(INPUT_POST, "report_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;

        $reports = $this->getReport($report_serial);

        if ($reports->count() == 0) {
            $this->logError("Invalid Report ({$report_serial}): " . __METHOD__);
        }

        $SQL = "delete from reports
                  where report_serial = {$report_serial}";

        $this->executeSQL($SQL);
    }

    // ===========
    // Edit Report
    // ===========

    public function editReport() {

        $step = filter_input(INPUT_POST, "step") ?: "prompt";

        switch ($step) {

            case "prompt":

                $report_serial = filter_input(INPUT_POST, "report_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;

                $reports = $this->getReport($report_serial);

                if ($reports->count() == 0) {
                    $this->logError("Invalid Report ({$report_serial}): " . __METHOD__);
                }

                $constants = $this->getConstants();

                $XML = $this->mergeXML($reports, "<XML/>");
                $XML = $this->mergeXML($constants, $XML);

                $content = $this->applyXSL($XML, $this->getXSL("editReport"));

                $this->displayContent($content);

                break;

            case "update":

                $report_serial = filter_input(INPUT_POST, "report_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
                $report_name = filter_input(INPUT_POST, "report_name") ?: "";
                $report_class = filter_input(INPUT_POST, "report_class") ?: "";
                $report_type = filter_input(INPUT_POST, "report_type") ?: "Report";
                $report_description = filter_input(INPUT_POST, "report_description") ?: "";
                $report_target = filter_input(INPUT_POST, "report_target") ?: "";

                $report_class = trim(preg_replace("/\s+/", " ", $report_class));

                $reports = $this->getReport($report_serial);

                if ($reports->count() == 0) {
                    $this->logError("Invalid Report ({$report_serial}): " . __METHOD__);
                }

                $SQL = "update reports
                   set report_class       = :report_class,
                       report_type        = :report_type,
                       report_name        = :report_name,
                       report_description = :report_description,
                       report_target      = :report_target
                 where report_serial      = :report_serial";

                $statement = $this->connect()->prepare($SQL);

                $statement->bindValue(":report_serial", $report_serial);
                $statement->bindValue(":report_class", $report_class);
                $statement->bindValue(":report_type", $report_type);
                $statement->bindValue(":report_name", $report_name);
                $statement->bindValue(":report_description", $report_description);
                $statement->bindValue(":report_target", $report_target);

                $statement->execute();

                break;

            default:

                $this->displayHome();
        }
    }

    // ======================
    // Return a Report Object
    // ======================

    public function getReport($report_serial = 0) {

        $SQL = "select view_reports.*
              from view_reports
             where report_serial = {$report_serial}";

        return $this->getTable("reports", $SQL);
    }

    // ===========================================
    // Return the report_serial for a report_class
    // ===========================================

    public function getReportSerial($report_class = "") {

        $SQL = "select view_reports.report_serial
              from view_reports
             where report_class = '{$report_class}'";

        $reports = $this->getTable("reports", $SQL);

        return (integer) ($reports->record->report_serial ?? 0);
    }

    // =======================
    // Return a Reports Object
    // =======================

    public function getReports() {

        $SQL = "select view_reports.*
              from view_reports";

        return $this->getTable("reports", $SQL);
    }

    // ============================
    // Return a Reports Page Object
    // ============================

    public function getReportsPage() {

        // Find Criteria

        $find_report = filter_input(INPUT_POST, "find_report") ?: "";
        $find_words = $this->sanitizeString($find_report);

//    $find_words = implode("|", explode(" ", $find_report));
        // Show Per Page

        $this->pagination_size = filter_input(INPUT_POST, "reports_per_page", FILTER_SANITIZE_NUMBER_INT) ?: $this->pagination_size;

        // Record Count

        $connection = $this->connect();

        $SQL = "select count(*) as count
              from view_reports
             where (report_class       regexp :report_class
                or  report_name        regexp :report_name
                or  report_type        regexp :report_type
                or  report_description regexp :report_description)";

        $statement = $connection->prepare($SQL);

        $statement->bindValue(":report_class", $find_words);
        $statement->bindValue(":report_name", $find_words);
        $statement->bindValue(":report_type", $find_words);
        $statement->bindValue(":report_description", $find_words);

        $statement->execute();

        $recordset = $statement->fetch(PDO::FETCH_ASSOC);

        $count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;

        // Pagination

        $pagination = filter_input(INPUT_POST, "pagination") ?: "";

        switch ($pagination) {

            case "first" : $this->pagination_page = 1;
                break;
            case "previous" : $this->pagination_page = max(($this->pagination_page - 1), 1);
                break;
            case "next" : $this->pagination_page = ($this->pagination_page + 1);
                break;
            case "last" : $this->pagination_page = ($count / $this->pagination_size);
                break;
        }

        $offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
        $start = ($offset + 1);
        $end = min($count, (($start + $this->pagination_size) - 1));

        // Data

        $SQL = "select view_reports.*
              from view_reports
             where (report_class       regexp :report_class
                or  report_name        regexp :report_name
                or  report_type        regexp :report_type
                or  report_description regexp :report_description)
             limit {$this->pagination_size}
            offset {$offset}";

        $statement = $connection->prepare($SQL);

        $statement->bindValue(":report_class", $find_words);
        $statement->bindValue(":report_name", $find_words);
        $statement->bindValue(":report_type", $find_words);
        $statement->bindValue(":report_description", $find_words);

        $statement->execute();

        $reports = $this->getTableXML("reports", $statement);

        // Insert Pagination Attributes

        $reports->addAttribute("count", $count);
        $reports->addAttribute("start", $start);
        $reports->addAttribute("end", $end);
        $reports->addAttribute("page", $this->pagination_page);

        $_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;

        return $reports;
    }

    // ==================================
    // Return a Select Report Page Object
    // ==================================

    public function getSelectReportPage() {

        // Find Criteria

        $select_report = filter_input(INPUT_POST, "select_report") ?: "";
        $find_words = $this->sanitizeString($select_report);

        // Show Per Page

        $this->pagination_size = filter_input(INPUT_POST, "reports_per_page", FILTER_SANITIZE_NUMBER_INT) ?: $this->pagination_size;

        // Record Count

        $connection = $this->connect();

        $SQL = "select count(*) as count
              from view_reports
             where report_name        regexp :report_name
                or report_description regexp :report_description";

        $statement = $connection->prepare($SQL);

        $statement->bindValue(":report_name", $find_words);
        $statement->bindValue(":report_description", $find_words);

        $statement->execute();

        $recordset = $statement->fetch(PDO::FETCH_ASSOC);

        $count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;

        // Pagination

        $pagination = filter_input(INPUT_POST, "pagination") ?: "";

        switch ($pagination) {

            case "first" : $this->pagination_page = 1;
                break;
            case "previous" : $this->pagination_page = max(($this->pagination_page - 1), 1);
                break;
            case "next" : $this->pagination_page = ($this->pagination_page + 1);
                break;
            case "last" : $this->pagination_page = ($count / $this->pagination_size);
                break;
        }

        $offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
        $start = ($offset + 1);
        $end = min($count, (($start + $this->pagination_size) - 1));

        // Data

        $SQL = "select view_reports.*
              from view_reports
             where report_name        regexp :report_name
                or report_description regexp :report_description
             limit {$this->pagination_size}
            offset {$offset}";

        $statement = $connection->prepare($SQL);

        $statement->bindValue(":report_name", $find_words);
        $statement->bindValue(":report_description", $find_words);

        $statement->execute();

        $reports = $this->getTableXML("reports", $statement);

        // Insert Pagination Attributes

        $reports->addAttribute("count", $count);
        $reports->addAttribute("start", $start);
        $reports->addAttribute("end", $end);
        $reports->addAttribute("page", $this->pagination_page);

        $_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;

        return $reports;
    }

    // ====================================
    // Determine if the Report Class Exists
    // ====================================

    public function reportExists() {

        $exists = false;

        $report_serial = filter_input(INPUT_POST, "report_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
        $report_class = filter_input(INPUT_POST, "report_class") ?: "";

        $report_class = trim(preg_replace("/\s+/", " ", $report_class));

        $SQL = "select report_serial
              from view_reports
             where report_serial      != :report_serial
               and lower(report_class) = :report_class";

        $statement = $this->connect()->prepare($SQL);

        $statement->bindValue(":report_serial", $report_serial);
        $statement->bindValue(":report_class", $report_class);

        $statement->execute();

        $recordset = $statement->fetchAll(PDO::FETCH_ASSOC);

        $exists = (count($recordset) > 0) ? true : false;

        echo json_encode($exists);
    }

    // ================
    // Select a Report.
    // ================

    public function selectReport() {

        $reports = $this->getSelectReportPage();
        $popovers = (new Popovers())->getPopovers();

        $XML = $this->mergeXML($reports, "<XML/>");
        $XML = $this->mergeXML($popovers, $XML);

        $content = $this->applyXSL($XML, $this->getXSL("selectReport"));

        $this->displayContent($content);
    }

    // =============
    // Setup Reports
    // =============

    public function setupReports() {

        $reports = $this->getReportsPage();
        $popovers = (new Popovers())->getPopovers();

        $XML = $this->mergeXML($reports, "<XML/>");
        $XML = $this->mergeXML($popovers, $XML);

        $content = $this->applyXSL($XML, $this->getXSL("setupReports"));

        $this->displayContent($content);
    }
}

?>
