<?php
/**
 * This file is part of the JustKnit package.
 *
 * @copyright JustKnit (Iris Hammer) <iris@justknit.de>
 * @license All rights reserved (@https://dejure.org/gesetze/UrhG/69a.html)
 * Created on 03-20-2023
 *
 * @package justknit
 */

namespace JustKnit\Register;
//namespace JustKnit\Controllers\Register;
use MODX\Revolution\modX;
use MODX\Revolution\modChunk;
use MODX\Revolution\Mail\modMail;
use JustKnit\Register\Dictionary;
use JustKnit\Register\Hooks;
use JustKnit\Register\Validator;
/**
 * Main Register class.
 *
 * @package justknit
 * @subpackage Register
 */

class Register
{
    /**
     * The constructor for the Register class.
     *
     * @param modX &$modx A reference to the modX instance
     * @param array $config An array of configuration properties
     */
    public function __construct(modX &$modx, array $config = [])
    {
        $this->modx = &$modx;
        $corePath = $this->modx->getOption(
            'justknit.core_path',
            $config,
            $this->modx->getOption(
                'core_path',
                null,
                MODX_CORE_PATH
            ) . 'components/justknit/'
        );
        $this->config = array_merge([
            'corePath'        => $corePath,
            'modelPath'       => $corePath . 'src/Model/',
            'controllersPath' => $corePath . 'src/Controllers/Register/',
            'processorsPath'  => $corePath . 'src/Processors/Register/',
            'chunksPath'      => $corePath . 'elements/chunks/',
        ], $config);
        $this->modx->lexicon->load('justknit:frontend');
    }

    /**
     * Load a Register controller by a given name.
     * (used by Snippets)
     *
     * @param string $controller
     * @return Controller object|null
     */
    public function loadController(string $controller)
    {
        $classPath = $this->config['controllersPath'] . $controller . '.php';
        $className = 'JustKnit\\Controllers\\Register\\' . $controller;
        if (file_exists($classPath)) {
            if (!class_exists($className)) {
                $className = require_once $classPath;
            }
            if (class_exists($className)) {
                $this->controller = new $className($this, $this->config);
            } else {
                $this->modx->log(
                    modX::LOG_LEVEL_ERROR,
                    '[JustKnit] Could not load controller ' . $className . ' at ' . $classPath
                );
            }
        } else {
            $this->modx->log(modX::LOG_LEVEL_ERROR, '[JustKnit] Could not find controller file: ' . $classPath);
        }
        return $this->controller;
    }

    /**
     * Load the Dictionary class and gather $_POST and $_GET params.
     *
     * @access public
     * @return Dictionary An instance of the Dictionary class
     */
    public function loadDictionary()
    {
        $this->dictionary = new Dictionary($this);
        // Load POST and GET parameters
        $this->dictionary->gather();
        return $this->dictionary;
    }

    /**
     * Load the Validator class and gather $_POST and $_GET params.
     *
     * @access public
     * @return Validator An instance of the Validator class
     */
    public function loadValidator()
    {
        $this->validator = new Validator($this);
        // Load POST and GET parameters
        return $this->validator;
    }    /**
     * Loads the Hooks class.
     *
     * @access public
     * @param string $type The name of the Hooks service to load (preHooks, postHooks)
     * @param array $config array An array of configuration parameters for the hooks class
     * @return Hooks An instance of the Hooks class
     */
    public function loadHooks(string $type, array $config = [])
    {
        $this->$type = new Hooks($this, $config);
        return $this->$type;
    }

    /**
     * Helper function to get a chunk or tpl by different methods.
     *
     * @access public
     * @param string $name The name of the tpl/chunk.
     * @param array $properties The properties to use for the tpl/chunk.
     * @param string $type The type of tpl/chunk. Can be embedded,
     * modChunk, file, or inline. Defaults to modChunk.
     * @return string The processed tpl/chunk.
     */
    public function getChunk($name,$properties,$type = 'modChunk') {
        $output = '';
        if (!is_array($properties) || is_null($properties)) $properties = array();
        switch ($type) {
            case 'embedded':
                if (!$this->modx->user->isAuthenticated($this->modx->context->get('key'))) {
                    $this->modx->setPlaceholders($properties);
                }
                break;
            case 'modChunk':
                $output = $this->modx->getChunk($name, $properties);
                break;
            case 'file':
                $name = str_replace(array(
                    '{base_path}',
                    '{assets_path}',
                    '{core_path}',
                ),array(
                    $this->modx->getOption('base_path'),
                    $this->modx->getOption('assets_path'),
                    $this->modx->getOption('core_path'),
                ),$name);
                $this->modx->setPlaceholders($properties);

                $chunk = $this->modx->newObject('modChunk');
                $chunk->setContent(file_get_contents($name));
                $chunk->setCacheable(false);
                $output = $chunk->process($properties);
                break;
            case 'inline':
            default:
                /* default is inline, meaning the tpl content was provided directly in the property */
                $chunk = $this->modx->newObject('modChunk');
                $chunk->setContent($name);
                $chunk->setCacheable(false);
                $output = $chunk->process($properties);
                break;
        }
        return $output;
    }
}
