<?php
/**
 * -------------------------------------------------------------------------
 *
 * The main application module.
 *
 * -------------------------------------------------------------------------
 *
 * @package    MimimiFramework
 * @subpackage Examples / IDE skeleton
 * @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 your IDE
         * projects, but will only simulate saving it.
         *
         * -----------------------------------------------------------------
         *
         * @var    bool
         * @access public
         *
         * -----------------------------------------------------------------
         */

        public $onProduction = FALSE;

        /**
         * -----------------------------------------------------------------
         *
         * Renders a page requested by the browser.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string  $dummy  It is always an empty string.
         * @return  void
         *
         * -----------------------------------------------------------------
         */

        public function run ( $dummy = '' ) {
            $method = mimimiServer ( 'REQUEST_METHOD' );
            switch ( $method ) {
                case 'HEAD':
                case 'GET':
                case 'POST':
                     $url = mimimiUri ( FALSE );
                     $this->renderByUrl ( $url );
                     break;
                case 'PUT':
                case 'DELETE':
                case 'CONNECT':
                case 'OPTIONS':
                case 'TRACE':
                case 'PATCH':
                default:
                     mimimiStop ( 'Error: Only methods like HEAD, GET, and POST are allowed when accessing this site.' );
            }
        }

        /**
         * -----------------------------------------------------------------
         *
         * Renders a page requested via the URL.
         *
         * -----------------------------------------------------------------
         *
         * Essentially, this method is used to route the browser's request
         * to the page associated with the current URL. This URL may have
         * been clicked through a menu or through a toolbar. Either it could
         * have been requested by a widget or via an API.
         *
         * This method routes the following URLs:
         *
         *     https://your.site/
         *     https://your.site/robots.txt
         *     https://your.site/projects/SOME-PROJECT-NAME
         *     https://your.site/projects/SOME-PROJECT-NAME/SOME-FILE-URL
         *     https://your.site/menu/SOME-MENU-ITEM-URL
         *     https://your.site/toolbars/SOME-TOOLBAR-ICON-URL
         *     https://your.site/widgets/SOME-WIDGET-URL
         *     https://your.site/api/SOME-API-URL
         *
         * Other URLs or those that are not currently supported will be
         * routed to the Error404 page. For example, URLs without parameters:
         *
         *     https://your.site/projects
         *     https://your.site/menu
         *     https://your.site/toolbars
         *     https://your.site/widgets
         *     https://your.site/api
         *
         * -----------------------------------------------------------------
         */

        public function renderByUrl ( $url ) {
            $this->runModule ( 'session' );
            switch ( $url ) {
                case '':
                     if ( $this->render ( 'home.tpl'   ) ) return;
                     break;
                case 'robots.txt':
                     if ( $this->render ( 'robots.tpl' ) ) return;
                     break;
                default:
                     $segments = preg_split  ( '~/~u', $url );
                     $target   = array_shift ( $segments    );
                     switch ( $target ) {
                         case 'projects':
                              $url = implode ( '/', $segments );
                              if ( $this->runModule ( $target, $url ) ) return;
                              break;
                         default:
                              if ( $this->checkForAdmin ( ) ) {
                                  switch ( $target ) {
                                      case 'menu':     $plan = [ 'menu',     'toolbars' ]; break;
                                      case 'toolbars': $plan = [ 'toolbars', 'menu'     ]; break;
                                      case 'widgets':  $plan = [ 'widgets',  'stop'     ]; break;
                                      case 'api':      $plan = [ 'api',      'stop'     ]; break;
                                      default:         $plan = [                        ];
                                  }
                                  if ( $plan ) {
                                      $url = implode ( '/', $segments );
                                      foreach ( $plan as $module ) {
                                          if ( $module == 'stop' ) mimimiStop ( '' );
                                          if ( $this->runModule ( $module, $url ) ) return;
                                      }
                                  }
                              }
                     }
            }
            return $this->renderNotFound ( )
                || mimimiStop ( '' );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Renders a template file by passing some data to it.
         *
         * -----------------------------------------------------------------
         */

        public function render ( $filename, $data = FALSE ) {
            return $this->runModule ( 'helper', $filename )
                && ( mimimiModule ( [ $filename, $data ] )
                     || TRUE );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Renders the page.
         *
         * -----------------------------------------------------------------
         *
         * Please note that such a page is always represented by the common
         * template "Themes/default/page.tpl", and its central part is
         * represented by the content template $filename, which must be
         * specified relative to the folder "Themes/default/snippets/content".
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string  $filename  The name of the template file that will be used to render the central part.
         * @return  bool               TRUE  if the page was rendered successfully.
         *                             FALSE if there is no template file for this page.
         *
         * -----------------------------------------------------------------
         */

        public function renderPage ( $filename ) {
            return $this->runModule ( 'helper', 'snippets/content/' . $filename )
                && $this->render    (           'page.tpl',           $filename );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Renders the page "Document Not Found" (Error 404).
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @return  bool  TRUE  if the page was rendered successfully.
         *                FALSE if there is no template file for this page.
         *
         * -----------------------------------------------------------------
         */

        public function renderNotFound ( ) {
            return $this->render ( 'error-404.tpl' );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Renders the page "Method Not Allowed" (Error 405).
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @return  bool  TRUE  if the page was rendered successfully.
         *                FALSE if there is no template file for this page.
         *
         * -----------------------------------------------------------------
         */

        public function renderNotAllowed ( ) {
            return $this->render ( 'error-405.tpl' );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Launches a module with some parameters.
         *
         * -----------------------------------------------------------------
         *
         * Module is a child directory and its PHP file with the same name.
         * Before launching a child module, we first check its presence
         * using the Has system module and, if successful, launch it with
         * the proposed parameters.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string  $modname  The name of the module to be launched.
         * @param   mixed   $params   (optional) Some incoming parameters that you want to pass when launching.
         * @return  bool              A boolean status of this launch.
         *
         * -----------------------------------------------------------------
         */

        public function runModule ( $modname, $params = '' ) {
            return $this->has->$modname
                && $this     ->$modname->run ( $params );
        }

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

        public function checkForAdmin ( ) {
            $entry = $this->projects->getUser ( );
            return ! empty ( $entry[ 'id' ] );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Reset the namespace simulator if you want to provide an ability
         * to extend this application with child modules that perform
         * various functions.
         *
         * According to the expected IDE structure, you will need at least
         * 4 child modules: Menu, Toolbars, Widgets, and Api. They assume
         * the presence of submodules with an unlimited level of nesting.
         *
         * Therefore, you should have an initialized namespace simulator
         * at each level of module nesting. However, the simulator can be
         * neglected if the functionality of nested modules is not tied to
         * their hierarchy.
         *
         * -----------------------------------------------------------------
         *
         * @var    string
         * @access protected
         *
         * -----------------------------------------------------------------
         */

        protected $myNodeFile = __FILE__;
    };
