<?php
namespace nur\config;

use nur\func;

/**
 * Interface IConfigManager: interface pour un gestionnaire de configuration
 */
interface IConfigManager {
  /** ajouter une classe ou un objet à la liste des configurateurs */
  function addConfigurator($configurators): void;

  /**
   * configurer les objets et les classes qui ne l'ont pas encore été. la liste
   * des objets et des classes à configurer est fournie en appelant la méthode
   * {@link addConfigurator()}
   *
   * par défaut, la configuration se fait en appelant toutes les méthodes
   * publiques des objets et toutes les méthodes statiques des classes qui
   * commencent par 'configure', e.g 'configureThis()' ou 'configure_db()',
   * si elles n'ont pas déjà été appelées
   *
   * Il est possible de modifier la liste des méthodes appelées avec le tableau
   * $options, qui doit être conforme au schema de {@link func::CALL_ALL_SCHEMA}
   */
  function configure(?array $options=null): void;

  /**
   * réinitialiser la liste des objets et des classes qui ont été configurés.
   */
  function resetConfiguration(): void;

  #############################################################################
  # gestion des objets
  #
  # la configuration est normalement stockée sous forme de tableau, et on accède
  # aux valeurs avec des chemins de clé. parfois, on peut souhaiter que la
  # valeur retournée pour un chemin de clé soit un objet, construit à partir de
  # la valeur présente dans la configuration pour ce chemin-là.
  #
  # les méthodes de cette section permettent d'implémenter ce mode opératoire

  /**
   * indiquer si la definition ou le chemin de clé spécifiés doit retourner un
   * objet.
   */
  function isObject($definition, ?string $pkey=null): bool;

  /**
   * créer un nouvel objet avec la définition spécifiée.
   *
   * - l'on peut choisir de se baser sur le chemin de clé $pkey pour savoir
   *   comment instancier l'objet.
   * - sinon, la définition sera un tableau de la forme
   *   [[$class], $args..., $key=>$values...]
   *   où $class est le nom de la classe d'objet, $args des arguments
   *   supplémentaires éventuels utilisés par le constructeur. les clés
   *   associatives sont utilisées pour faire un tableau qui est passé en
   *   dernier argument.
   */
  function newObject($definition, ?string $pkey=null);

  #############################################################################

  /** spécifier le code application. */
  function initAppcode(string $appcode): void;

  /** obtenir le code application, utilisé pour les autorisations d'accès */
  function getAppcode(): string;

  const PROD = "prod";
  const TEST = "test";
  const DEVEL = "devel";
  const DEFAULT_PROFILES = [
    self::PROD,
    self::TEST,
    self::DEVEL,
  ];

  /**
   * clé de profil à utiliser pour le profil par défaut (c'est à dire que les
   * valeurs sont valides pour tous les profils)
   */
  const PROFILE_ALL = "ALL";

  /**
   * spécifier le profil à sélectionner par défaut si l'utilisateur n'en n'a pas
   * fourni
   */
  function setDefaultProfile(?string $defaultProfile): void;

  /** retourner la liste des profils valides */
  function getProfiles(): array;

  /** spécifier le profil courant. */
  function setProfile(string $profile): void ;

  /**
   * obtenir le profile courant.
   *
   * si le profil courant n'est pas défini:
   * - si $ensureNn est vrai, calculer le profil courant
   * - sinon retourner null
   *
   * le profil courant est calculé à partir *des données de l'environnement*
   * si aucun profil n'a été spécifié par l'utilisateur dans l'environnement,
   * choisir:
   * - le profil spécifié par {@link setDefaultProfile()} ou
   * - le premier profil de {@link getProfiles()}
   */
  function getProfile(bool $ensureNn=true): ?string;

  #############################################################################

  /**
   * Ajouter une configuration valide pour le(s) profil(s) spécifié(s)
   *
   * $config est:
   * - soit une classe qui définit une ou plusieurs des constantes SCHEMA, DBS,
   *   MSGS, MAILS, APP, USER
   * - soit une instance de {@link DynConfig}
   *
   * si $inProfiles===null, la configuration est valide dans tous les profils
   */
  function addConfig($config, ?array $inProfiles=null): void;

  /**
   * obtenir la valeur au chemin de clé $pkey dans le profil spécifié
   *
   * le $inProfile===null, prendre le profil par défaut.
   */
  function getValue(string $pkey, $default=null, ?string $inProfile=null);

  #############################################################################

  /** affirmer un fait, information qui peut être utilisée par l'application */
  function setFact(string $fact, $value=true): void;

  /** tester si un fait est avéré */
  function isFact(string $fact, $value=true): bool;

  /** spécifier le mode DEBUG */
  function setDebug(?bool $debug=true): void;
  /** est-on en mode DEBUG? */
  function isDebug(): bool;
}