<?php

namespace EesyPHP\Auth;

use EesyPHP\Log;
use function EesyPHP\ensure_is_array;

class User {

  /**
   * Username
   * @var string
   */
  private $username;

  /**
   * User backend class name
   * @var string
   */
  private $backend;

  /**
   * User info
   * @var array<string,mixed>
   */
  private $info;

  /**
   * Constructor
   * @param string $username The username
   * @param string $backend The backend class name
   * @param array<string,mixed>|null $info User info (optional)
   */
  public function __construct($username, $backend, $info=null) {
    $this -> username = $username;
    $this -> backend = $backend;
    $this -> info = is_array($info)?$info:array();
  }

  /**
   * Magic method to get a dynamic property
   * @param string $key The property
   * @return mixed
   */
  public function __get($key) {
    switch ($key) {
      case 'username':
        return $this -> username;
      case 'backend':
        return $this -> backend;
      case 'info':
        return $this -> info;
      default:
        if (array_key_exists($key, $this -> info))
          return $this -> info[$key];
    }
    Log::warning(
      'Ask for unknown user property %s:\n%s', $key, Log::get_debug_backtrace_context());
    return null;
  }

  /**
   * Magic method to set a dynamic property
   * @param string $key The property
   * @param mixed $value The value
   * @return void
   */
  public function __set($key, $value) {
    switch ($key) {
      case 'username':
        $this -> username = strval($value);
        break;
      case 'backend':
        $this -> backend = strval($value);
        break;
      case 'info':
        $this -> info = ensure_is_array($value);
        break;
      default:
        $this -> info[$key] = $value;
    }
  }

  /**
   * Magic method to check if a dynamic property is set
   * @param string $key The property
   * @return bool
   */
  public function __isset($key) {
    switch ($key) {
      case 'username':
      case 'backend':
      case 'info':
        return true;
      default:
        return array_key_exists($key, $this -> info);
    }
  }

  /**
   * Check user password
   * @param string $password
   * @return bool
   */
  public function check_password($password) {
    return call_user_func(
      array($this -> backend, 'check_password'),
      $this, $password
    );
  }

  /**
   * Magic method to allow pretty cast to string
   * @return string
   */
  public function __toString() {
    if (isset($this -> name))
      return sprintf('%s (%s)', $this -> name, $this -> username);
    return $this -> namename;
  }

}
