<?php

namespace EesyPHP;

class App {

  /**
   * Options
   * @var array
   */
  protected static $options = array();

  /**
   * Root directory path
   * @var string|null
   */
  protected static $root_directory_path = null;

  /**
   * Initialization
   * @param string|null $config_file Application configuration file path
   * @param array|null $options Application options (default: null)
   * @param string|null $root_directory_path Application root directory path (default: null)
   * @return void
   */
  public static function init($config_file, $options=null, $root_directory_path=null) {
    if (is_array($options)) self :: $options = $options;

    if (is_null($root_directory_path)) {
      $traces = debug_backtrace();
      $root_directory_path = realpath(dirname($traces[0]['file']).'/../');
    }
    self :: $root_directory_path = $root_directory_path;
    Config::register_extra_variable('root_directory_path', $root_directory_path);

    $config_file = Config::replace_variables($config_file);
    if (!Config::load($config_file)) {
      Log::fatal('Fail to load configuration file (%s)', $config_file);
      exit(1);
    }

    // Load overwrite configuration file
    foreach (self :: get_option('overwrite_config_files', array(), 'array') as $file) {
      $file = Config::replace_variables($file);
      if (is_file($file)) Config::load($file, true);
    }

    if (self :: get_option('sentry.enabled', true, 'bool'))
      SentryIntegration :: init();
    $sentry_transaction = new SentryTransaction();
    $sentry_span = new SentrySpan('app.init', 'Application initialization');

    // Define upload_tmp_dir
    if (is_string(Config::get('upload_tmp_directory')))
      ini_set('upload_tmp_dir', Config::get('upload_tmp_directory'));

    if (self :: get_option('log.enabled', true, 'bool'))
      Log::init();
    if (self :: get_option('session.enabled', true, 'bool'))
      Session::init();
    if (self :: get_option('template.enabled', true, 'bool'))
      Tpl :: init();
    if (self :: get_option('url.enabled', true, 'bool'))
      Url::init();
    if (self :: get_option('mail.enabled', true, 'bool'))
      Email :: init();
    if (self :: get_option('i18n.enabled', true, 'bool'))
      I18n::init();
    $sentry_span->finish();
  }

  /**
   * Get a specific option value
   *
   * @param string $key The configuration variable key
   * @param mixed $default The default value to return if configuration variable
   *                       is not set (Default : null)
   * @param string $cast   The type of expected value. The configuration variable
   *                       value will be cast as this type. Could be : bool, int,
   *                       float or string. (Optional, default : raw value)
   * @param bool $split If true, $cast is 'array' and value retreived from configuration
   *                    is a string, split the value by comma (optional, default: true)
   * @return mixed The configuration variable value
   **/
  public static function get_option($key, $default=null, $cast=null, $split=true) {
    return Config::get(
      $key,
      Config::loaded()?Config::get($key, $default, $cast, $split):$default,
      $cast,
      $split,
      self :: $options
    );
  }

  /**
   * Retreive application root directory path
   * @return string|null
   */
  public static function root_directory_path() {
    return self :: $root_directory_path?self :: $root_directory_path:'.';
  }

}