<?php

declare(strict_types=1);

/**
 * This file is part of LEPTON Core, released under the GNU GPL
 * Please see LICENSE and COPYING files in your package for details, specially for terms and warranties.
 *
 * NOTICE:LEPTON CMS Package has several different licenses.
 * Please see the individual license in the header of each single file or info.php of modules and templates.
 *
 * @author          LEPTON Project
 * @copyright       2010-2026 LEPTON Project
 * @link            https://lepton-cms.org
 * @license         https://gnu.org/licenses/gpl.html
 * @license_terms   please see LICENSE and COPYING files in your package
 *
 */

/**
 *  This is only an abstract class for LEPTON-frontend use specific classes and inside modules.
 *
 */

abstract class LEPTON_abstract_frontend
{

    /**
     * Default string if a value is not set in the info.php of the module.
     * @type    string
     *
     */
    const NOT_SET_IN_INFO = "(unknown - not set in info.php)";

    /**
     *  Array with the language(-array) of the child-object.
     *  @type   array
     *
     */
    public array $language = [];

    /**
     *  Array with the names of all parents (desc. order)
     *  @type   array
     *
     */
    public array $parents = [];

    /**
     *  The module description from the info.php of the child.
     *  @type   string
     *
     */
    public string $module_description = "";

    /**
     * Instance of the class.
     * @var object|null
     */
    public static $instance;


    /**
     *  Return the instance of this class.
     *
     */
    public static function getInstance(mixed $value = null): object
    {
        if (null === static::$instance)
        {
            static::$instance = new static();
            static::$instance->getParents();
            static::$instance->getLanguageFile();
            static::$instance->initialize($value);
        }
        return static::$instance;
    }

    /**
     * Get all class constants as an assoc. array.
     *
     * @return array
     */
    public static function getConstants(): array
    {
        // "static::class" here does the magic
        $reflectionClass = new ReflectionClass(static::class);
        return $reflectionClass->getConstants();
    }

    /**
     *  Private function to "handle" sub_class-names
     * @param string $anyClassname
     * @return array
     */
    protected function getMainClassNames(string $anyClassname): array
    {
        $aElements = explode("_", $anyClassname);

        $sTempName = array_shift($aElements);

        $aReturnValue = [$sTempName];

        foreach ($aElements as $term)
        {
            $sTempName .= "_" . $term;
            $aReturnValue[] = $sTempName;
        }

        if (count($aReturnValue) > 1)
        {
            $aReturnValue = array_reverse($aReturnValue);
        }

        return $aReturnValue;
    }

	
    /**
     *  Try to get a module-specific language file.
     */
    protected function getLanguageFile(): void
    {
        if(defined("LEPTON_PATH"))
        {
            $aLookUpFilenames = [
                LANGUAGE."_add.php",
                LANGUAGE."_custom.php",
                LANGUAGE.".php",
                "EN_add.php",
                "EN_custom.php",
                "EN.php"
            ];

            foreach( static::$instance->parents as $sClassNameTop)
            {
                //  strip namespace
                $aTemp = explode("\\", $sClassNameTop);
                $bExitGraceful = false;
                foreach ($aTemp as $sClassName)
                {          
                    $aMainClassNames = $this->getMainClassNames($sClassName);

                    foreach($aMainClassNames as $sTempModuleDirectory)
                    {
                        $lookUpPath = LEPTON_PATH."/modules/".$sTempModuleDirectory."/languages/";

                        $bFoundFile = false;

                        $sUsedFilename = "";
                        foreach ($aLookUpFilenames as $sTempFilename)
                        {
                            if (true === file_exists($lookUpPath.$sTempFilename))
                            {
                                require $lookUpPath.$sTempFilename;
                                $sUsedFilename = $sTempFilename;
                                $bFoundFile = true;
                                break;
                            }
                        }

                        if(false === $bFoundFile)
                        {
                            continue;
                        }

                        $tempName = "MOD_".strtoupper($sTempModuleDirectory);
                        if (isset(${$tempName}))
                        {
                            /**
                             *  Is this is a "*_add.php" language file?
                             */
                            if (str_contains($sUsedFilename, "_add.php"))
                            {
                                $sDefaultFileName = str_replace("_add", "", $sUsedFilename);
                                $aLanguageAdd = ${$tempName};

                                require $lookUpPath.$sDefaultFileName;

                                ${$tempName} = array_merge(${$tempName}, $aLanguageAdd);
                            }

                            static::$instance->language = ${$tempName};
                            $bExitGraceful = true;
                            break;
                        }
                    }
                    
                    if (true === $bExitGraceful)
                    {
                        break;
                    }
                }
            }
        }
    }


    /**
     *  Try to get all parents form the current instance as a simple linear list.
     */
    protected function getParents(): void
    {
        // First the class itself
        static::$instance->parents[] = get_class(static::$instance);

        // Now the parents
        $aTempParents = class_parents(static::$instance, true);
        foreach($aTempParents as $sParentName)
        {
            static::$instance->parents[] = $sParentName;
        }
    }

    /**
     *  Abstract declarations - has to be overwritten by the child-instance.
     */
    abstract protected function initialize();

}