<?php 
 
 
namespace App\Settings; 
 
use App\Entity\Setting; 
use App\Repository\SettingRepository; 
use Doctrine\ORM\EntityManagerInterface; 
use Twig\Environment; 
 
abstract class AbstractSettingsManager implements SettingsManagerInterface 
{ 
    protected SettingRepository $settingRepository; 
    protected EntityManagerInterface $entityManager; 
    protected Environment $twig; 
 
    protected array $settings = []; 
 
    public function __construct( 
        SettingRepository $settingRepository, 
        EntityManagerInterface $entityManager, 
        Environment $twig 
    ) { 
        $this->settingRepository = $settingRepository; 
        $this->entityManager = $entityManager; 
        $this->twig = $twig; 
 
        $this->settings = $this->configureSettings(); 
    } 
 
    /** 
     * @param string|array $settingNames 
     * @return Setting|Setting[] 
     */ 
    public function get($settingNames, bool $onlyValues = false) { 
        if (is_iterable($settingNames)) { 
            $settings = $this->settingRepository 
                ->findBy(['name' => $settingNames]) 
            ; 
 
            if ($onlyValues) { 
                $result = []; 
                foreach ($settings as $setting) { 
                    $result[$setting->getName()] = $setting->getValue(); 
                } 
                return $result; 
            } 
 
            return $settings; 
        } 
 
        $setting = $this->settingRepository 
            ->findOneBy(['name' => $settingNames]) 
        ; 
 
        if ($onlyValues) { 
            return $setting->getValue(); 
        } 
 
        return $setting; 
    } 
 
    public function getValue(string $settingName): string { 
        return $this->get($settingName, true); 
    } 
 
    public function synchronize(bool $overwrite, bool $deleteOrphans): array 
    { 
        // Initialize counters for logging 
        $deletedSettingCount = 0; 
        $createdSettingCount = 0; 
        $modifiedSettingCount = 0; 
 
        // Get all the setting existing in the database 
        $savedSettings = $this->settingRepository->findAll(); 
 
        // Determining which setting to look for in the database 
        $settings = $this->settings; 
        // If the settingNames argument is null or empty, we observe all setting 
        $allSettingNames = array_keys($settings); 
 
        // Process existing setting 
        $existingSettingNames = []; 
        foreach ($savedSettings as $savedSetting) { 
            $name = $savedSetting->getName(); 
            // Delete non matching parameters 
            if (in_array($name, $allSettingNames) === false) { 
                $this->entityManager->remove($savedSetting); 
                $deletedSettingCount++; 
            } else { 
                $existingSettingNames[] = $name; 
 
                // Update type and value to default when overwrite is true 
                if($overwrite === true) { 
                    $savedSetting->setDisplayName($settings[$name]['displayName']); 
                    $savedSetting->setValue($this->getDefaultValue($name)); 
                    $modifiedSettingCount++; 
                } 
            } 
        } 
 
        // Create new Settings when necessary 
        foreach (array_diff($allSettingNames, $existingSettingNames) as $newSettingName) { 
            $setting = new Setting(); 
            $setting->setName($newSettingName); 
            $setting->setValue($this->getDefaultValue($newSettingName)); 
            $setting->setDisplayName($settings[$newSettingName]['displayName']); 
 
            $this->entityManager->persist($setting); 
            $createdSettingCount++; 
        } 
 
        return [ 
            'deleted' => $deletedSettingCount, 
            'created' => $createdSettingCount, 
            'modified' => $modifiedSettingCount 
        ]; 
    } 
 
    public function getDefaultValue(string $settingName): ?string { 
        $settingDefaultData = $this->settings[$settingName]; 
        $originalValue = isset($settingDefaultData['default']) ? $settingDefaultData['default'] : null; 
 
        // Apply logic to get actual value 
        return $originalValue; 
    } 
}