<?php
/**
 * -------------------------------------------------------------------------
 *
 * The main module for receiving requests.
 *
 * -------------------------------------------------------------------------
 *
 * This module is always called using run() methow implemented below. It just
 * launches your application and routes the requested URL to a template file
 * associated with that page type. The initiator of calling run() method is
 * the root file "index.php" of your website.
 *
 * The second method implemented below is render(), which is called from
 * run() method to render a successfully routed template file. All these
 * templates are located in "Themes/default" folder as files with ".tpl"
 * extension.
 *
 * There is also a third method. It's getCustomerId() to retrieve a customer
 * identifier if that user is currently logged in. Otherwise, this method
 * returns a null ID.
 *
 * At this moment, getCustomerId() method contains a simple algorithm for
 * demonstration purposes only and is marked below with the word "TODO:".
 * Please replace it with your production algorithm.
 *
 * -------------------------------------------------------------------------
 *
 * @package    MimimiFramework
 * @subpackage Examples / Shopping UI with Vue.js
 * @license    GPL-2.0
 *             https://opensource.org/license/gpl-2-0/
 * @copyright  2022 MiMiMi Community
 *             https://mimimi.software/
 *
 * -------------------------------------------------------------------------
 */

    mimimiLoad    ( 'RoutinesWeb.php' );
    mimimiInclude ( 'NodeModule.php'  );

    class MyMimimiApplication extends MimimiNodeModule {

        /**
         * -----------------------------------------------------------------
         *
         * Set this property to FALSE if you are currently working in demo
         * mode. This will prevent the data from being saved to the database,
         * but will only simulate saving it. To understand this property,
         * please review the following template files:
         *
         *     Themes/default/order-add.tpl
         *     Themes/default/product-add.tpl
         *     Themes/default/vendor-add.tpl
         *     Themes/default/vendor-delete.tpl
         *     Themes/default/vendor-edit.tpl
         *
         * -----------------------------------------------------------------
         */

        public $onProduction = FALSE;

        /**
         * -----------------------------------------------------------------
         *
         * Routes the page URL requested by the user's browser.
         *
         * -----------------------------------------------------------------
         *
         * This method handles the following URLs and routes them to the
         * associated template file:
         *
         *     https://your.site/                        to see a home page
         *     https://your.site/robots.txt              to generate "robotx.txt" document
         *     https://your.site/sitemap.xml             to generate sitemap document
         *
         *     https://your.site/customer/json           to request current customer data as JSON
         *
         *     https://your.site/order/add               to order products currently in your cart
         *     https://your.site/order/SOME-ORDER-URL    to see an order page
         *
         *     https://your.site/add                     to add a new vendor
         *     https://your.site/SOME-VENDOR-URL/add     to add a new vendor product
         *     https://your.site/SOME-VENDOR-URL/delete  to delete a vendor
         *     https://your.site/SOME-VENDOR-URL/edit    to edit a vendor
         *     https://your.site/SOME-VENDOR-URL/json    to request vendor products as JSON
         *     https://your.site/SOME-VENDOR-URL         to see a vendor page
         *
         *     https://your.site/UNDEFINED-URL           to see an Error404 page
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   mixed  $params  (optional) It's a dummy that isn't really used here.
         * @return  void
         *
         * -----------------------------------------------------------------
         */

        public function run ( $params = '' ) {
            $template = '';
            $data     = FALSE;
            $url      = mimimiUri ( FALSE );
            switch ( $url ) {
                case '':
                     $template = 'home.tpl';
                     break;
                case 'robots.txt':
                     $template = 'robots.tpl';
                     break;
                case 'sitemap.xml':
                     $template = 'sitemap.tpl';
                     $data     = $this->vendors->getVendors ( );
                     break;
                case 'add':
                     $template = $this->checkForAdmin ( )
                                             ? 'vendor-add.tpl'
                                             : '';
                     break;
                default:
                     $segments = preg_split ( '~/~u', $url );
                     switch ( $segments[ 0 ] ) {
                         case 'customer':
                                     array_shift (      $segments );
                              $url = implode     ( '/', $segments );
                              switch ( $url ) {
                                  case '':
                                       break;
                                  case 'json':
                                       $cid      = $this->getCustomerId ( );
                                       $template = 'customer-json.tpl';
                                       $data     = $cid ? $this->customers->getById ( $cid )
                                                        : FALSE;
                                       break;
                              }
                              break;
                         case 'order':
                                     array_shift (      $segments );
                              $url = implode     ( '/', $segments );
                              switch ( $url ) {
                                  case '':
                                       break;
                                  case 'add':
                                       $template = 'order-add.tpl';
                                       break;
                                  default:
                                       $data = $this->orders->getByUrl ( $url );
                                       if ( $data ) {
                                           $template = 'order.tpl';
                                       }
                              }
                              break;
                         default:
                              $method  = 'getByUrl';
                              $command = array_pop ( $segments );
                              switch ( $command ) {
                                  case 'add':
                                       $template = $this->checkForAdmin ( )
                                                               ? 'product-add.tpl'
                                                               : '';
                                       break;
                                  case 'delete':
                                       $template = $this->checkForAdmin ( )
                                                               ? 'vendor-delete.tpl'
                                                               : '';
                                       break;
                                  case 'edit':
                                       $template = $this->checkForAdmin ( )
                                                               ? 'vendor-edit.tpl'
                                                               : '';
                                       break;
                                  case 'json':
                                       $template = 'vendor-json.tpl';
                                       $method   = 'getProducts';
                                       break;
                                  default:
                                       $template = 'vendor.tpl';
                                       $segments[ ] = $command;
                              }
                              if ( $template ) {
                                  $url = implode ( '/', $segments );
                                  if ( $url ) {
                                      $data = $this->vendors->$method ( $url );
                                  }
                                  if ( ! $data ) {
                                      $template = '';
                                  }
                              }
                     }
            }
            $this->render ( $template == ''
                                       ? 'error404.tpl'
                                       : $template,
                            $data );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Renders the theme template file.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string  $template  The name of the template file that will be rendered.
         * @param   mixed   $data      (optional) Data to be sent to that template.
         * @return  void
         *
         * -----------------------------------------------------------------
         */

        public function render ( $template, $data = FALSE ) {
            $this->helper->run ( );
            mimimiModule (
                [ $template, $data ]
            );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Computes a hash of the password.
         *
         * -----------------------------------------------------------------
         *
         * It implements the simplest algorithm for computing a hash. But if
         * your site must provide high resistance to attacks, it is highly
         * recommended to use a more complex algorithm.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string  $password
         * @return  string
         *
         * -----------------------------------------------------------------
         */

        public function hashPassword ( $password ) {
            return md5 ( $password );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Checks if the current visitor has an administrative role.
         *
         * -----------------------------------------------------------------
         *
         * @protected
         * @return  bool
         *
         * -----------------------------------------------------------------
         */

        protected function checkForAdmin ( ) {
            return $this->onProduction
                            ? TRUE     // <-- TODO: replace it with a real verification
                            : TRUE;    // <-- in demo mode we consider any visitor as an admin
        }

        /**
         * -----------------------------------------------------------------
         *
         * Retrieves an identifier of the current customer.
         *
         * -----------------------------------------------------------------
         *
         * @protected
         * @return  int
         *
         * -----------------------------------------------------------------
         */

        protected function getCustomerId ( ) {
            return $this->onProduction
                            ? 0        // <-- TODO: replace it with a real retrieving of customer ID
                            : 1;       // <-- in demo mode we consider any visitor as a customer with ID = 1
        }

        /**
         * -----------------------------------------------------------------
         *
         * Reset namespace simulator.
         *
         * -----------------------------------------------------------------
         */

        protected $myNodeFile = __FILE__;
    };
