<?php

// Namespace
namespace BMI\Plugin\Checker;

// Use
use BMI\Plugin\Backup_Migration_Plugin as BMP;
use BMI\Plugin\BMI_Logger as Logger;

/**
 * Class System_Info
 */
class System_Info {
  /**
   * Get the available memory
   *
   * @var float|int   // flot|int
   */
  protected $memory_available;

  /**
   * Get the PHP version
   *
   * @var float   // Version
   */
  protected $php_version;

  /**
   * Get the MySQL version
   *
   * @var float   // MySQL version
   */
  protected $mysql_version;

  /**
   * Get the webserver
   *
   * @var String   // webserver used.
   */
  protected $webserver;

  /**
   * Get the Operating Server
   *
   * @var String   // OS used.
   */
  protected $os;
  /**
   * Get the Free Space After Backup
   *
   * @var false|float|int
   */
  protected $free_space_after_backup;
  
  protected $timezone;
  protected $upload_dir_url;
  protected $is_multisite;
  protected $active_plugins;
  protected $wp_active_themes_info;
  protected $operating_system;
  protected $disk_free_space;
  protected $php_version_primary;
  protected $php_version_secondary;
  protected $php_version_minor;
  protected $php_loaded_extensions;
  protected $disable_functions;
  protected $backtrack_limit;

  public function is_enabled($func) {

    $disabled = explode(',', ini_get('disable_functions'));
    $isDisabled = in_array($func, $disabled);
    if (!$isDisabled && function_exists($func)) return true;
    else return false;

  }

  /**
   * Get the timezone from WordPress details.
   *
   * @return String // timezone
   */
  public function get_timezone() {
    if (! isset($this->timezone)) {
      if (function_exists('wp_timezone')) {
        $this->timezone = wp_timezone()->getName();
      } else {
        $date = new \DateTime();
        $time_zone = $date->getTimezone();
        $this->timezone = $time_zone->getName();
      }
    }

    return $this->timezone;
  }

  /**
   * Get the Webserver by executing shell details.
   *
   * @return String // webserver name
   */
  public function get_webserver() {
    if (! isset($this->webserver)) {
      if (isset($_SERVER['SERVER_SOFTWARE'])) {
        $this->webserver = sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE']));
      }
    }

    return $this->webserver;
  }

  /**
   * Get the Webserver from phpinfo details.
   *
   * @return String // os  fingureprint
   */
  public function get_os() {
    if ($this->is_enabled('php_uname')) {
      if (! isset($this->os)) {
        $this->os = strtolower(php_uname('s'));
      }

      return $this->os;
    } else {
      return __('Blocked by hosting', 'backup-backup');
    }
  }

  /**
   * Get the homeurl from WordPress details.
   *
   * @return String // os
   */
  public function get_operating_system() {
    if ($this->is_enabled('php_uname')) {
      if (! isset($this->operating_system)) {
        $this->operating_system = php_uname('s') . ' ' . php_uname('v');
      }

      return $this->operating_system;
    } else {
      return __('Blocked by hosting', 'backup-backup');
    }
  }

  /**
   * Get the upload directory url from WordPress details.
   *
   * @return String //  upload directory url
   */
  public function get_upload_dir_url() {
    if (! isset($this->upload_dir_url)) {
      $upload_dir_url = wp_get_upload_dir();
      $this->upload_dir_url = $upload_dir_url['baseurl'];
    }

    return $this->upload_dir_url;
  }

  /**
   * Get the content directory
   *
   * @return String //  content directory
   */
  public function get_content_dir() {
    if (! isset($this->content_dir)) {
      $content_dir = plugin_dir_path(WP_CONTENT_DIR . '/' . 'plugins/');
      $this->content_dir = $content_dir;
    }

    return $this->content_dir;
  }

  /**
   * Get the plugin directory from WordPress details.
   *
   * @return String //  plugin directory
   */
  public function get_plugin_dir() {
    if (! isset($this->plugin_dir)) {
      $plugin_dir = plugin_dir_path(WP_CONTENT_DIR . '/plugins/plugin-folder');
      $this->plugin_dir = $plugin_dir;
    }

    return $this->plugin_dir;
  }

  /**
   * Get the active plugins.
   *
   * @return String //  active plugins
   */
  public function get_active_plugins_info() {
    if (! isset($this->active_plugins)) {
      $active_plugins = get_option('active_plugins', false);

      $arr_active_plugins = [];

      foreach ($active_plugins as $path) {
        $arr_data = [];
        if (! function_exists('get_plugin_data')) {
          require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $path);
        if (
                    isset($plugin_data['Name']) && ! empty($plugin_data['Name'])
                    && isset($plugin_data['Version']) && ! empty($plugin_data['Version'])
                ) {
          $arr_data['name'] = $plugin_data['Name'];
          $arr_data['version'] = $plugin_data['Version'];
          $arr_data['slug'] = $plugin_data['TextDomain'];

          array_push($arr_active_plugins, $arr_data);
          unset($arr_data);
        }
      }
      $this->active_plugins = $arr_active_plugins;
    }

    return $this->active_plugins;
  }

  /**
   * Get the check  multisite.
   *
   * @return bool //  check multisite
   */
  public function check_multisite() {
    if (! isset($this->is_multisite)) {
      $this->is_multisite = is_multisite();
    }

    return $this->is_multisite;
  }

  /**
   * Get the disk free space
   *
   * @return float // disk free space
   */
  public function get_disk_free_space() {
    if ($this->is_enabled('disk_free_space')) {
      if (!isset($this->disk_free_space)) {
        $this->disk_free_space = \disk_free_space(ABSPATH);
      }

      return $this->disk_free_space;
    } else {
      return __('Blocked by hosting', 'backup-backup');
    }
  }

  /**
   * Get the php version
   *
   * @return String // php version
   */
  public function get_php_version() {
    if (! isset($this->php_version)) {
      $this->php_version = explode(' ', phpversion())[0];
    }

    return $this->php_version;
  }

  /**
   * Get the php loaded extensions
   *
   * @return String // php loaded extensions
   */
  public function get_php_loaded_extensions() {
    if (! isset($this->php_loaded_extensions)) {
      $this->php_loaded_extensions = get_loaded_extensions();
    }

    return $this->php_loaded_extensions;
  }

  /**
   * Get the disable functions
   *
   * @return String // disable functions
   */
  public function get_php_disable_functions() {
    if (! isset($this->disable_functions)) {
      $this->disable_functions = explode(',', ini_get('disable_functions'));
    }

    return $this->disable_functions;
  }

  /**
   * Get the backtrack limit
   *
   * @return String // backtrack limit
   */
  public function get_backtrack_limit() {
    if (! isset($this->backtrack_limit)) {
      $this->backtrack_limit = (int) ini_get('pcre.backtrack_limit');
    }

    return $this->backtrack_limit;
  }

  /**
   * Get the is mysql character set
   *
   * @return String // mysql character set
   */
  public function get_mysql_character_set() {
    global $wpdb;
    if (! isset($this->get_mysql_character_set)) {
      $charset_query = $wpdb->get_charset_collate();
      $matches = [];
      preg_match('/SET\s+(\w+)/', $charset_query, $matches);
      if (count($matches) > 1) {
        return $matches[1];
      }
    }

    return '';
  }

  /**
   * Get the is get active_themes_info
   *
   * @return String // active_themes_info
   */
  public function get_active_themes_info() {
    if (! isset($this->wp_active_themes_info)) {
      $arr_active_themes = [];
      $theme = wp_get_theme();
      $theme_name = $theme->get('TextDomain');
      $theme_version = $theme->get('TextDomain');
      if (
                isset($theme_name) && ! empty($theme_name)
                && isset($theme_version) && ! empty($theme_version)
            ) {
        $arr_data['name'] = $theme->get('Name');
        $arr_data['version'] = $theme->get('Version');
        $arr_data['slug'] = $theme->get('TextDomain');

        array_push($arr_active_themes, $arr_data);
        unset($arr_data);
      }
      $this->wp_active_themes_info = $arr_active_themes;
    }

    return $this->wp_active_themes_info;
  }

  /**
   * Get the is get php_version_primary()
   *
   * @return String // php_version_primary()
   */
  public function get_php_version_primary() {
    if (! isset($this->php_version_primary)) {
      $this->php_version_primary = explode('.', $this->get_php_version());

      return $this->php_version_primary[0];
    }
  }

  /**
   * Get the is get php_version_secondary()
   *
   * @return String // php_version_secondary()
   */
  public function get_php_version_secondary() {
    if (! isset($this->php_version_secondary)) {
      $this->php_version_secondary = explode('.', $this->get_php_version());

      return $this->php_version_secondary[1];
    }
  }

  /**
   * Get the is get php_version_minor()
   *
   * @return String // php_version_minor()
   */
  public function get_php_version_minor() {
    if (! isset($this->php_version_minor)) {
      $this->php_version_minor = explode('.', $this->get_php_version());

      return $this->php_version_minor[2];
    }
  }

  /**
   * Check if cURL is work properly
   * 
   * @return bool 
   */
  public static function is_curl_work() {
    return function_exists('curl_version') && function_exists('curl_exec') && function_exists('curl_init') && BMP::isFunctionEnabled('curl_init') && BMP::isFunctionEnabled('curl_exec');
  }

  /**
   * Check if php cli is runnable
   * 
   * @return bool
   */
  public static function is_php_cli_runnable() {
    return BMP::isFunctionEnabled('exec') && BMP::isFunctionEnabled('shell_exec') && BMP::isFunctionEnabled('system');
  }

  /**
   * Get changes human redeable sizes to numbers()
   *
   * @param String $num // readble size to be converted to byte
   *
   * @return number // readble_size_to_bytes()
   */
  public function readble_size_to_bytes($num) {
    $num_split = str_split(strval(strtolower($num)));
    $num_split_temp = $num_split;
    $num_end = end($num_split);
    array_pop($num_split);
    $num_join = implode('', $num_split);
    if ('m' === $num_end) {
      $num = doubleval($num_join) * 1048576;
    } elseif ('k' === $num_end) {
      $num = doubleval($num_join) * 1024;
    } elseif ('g' === $num_end) {
      $num = doubleval($num_join) * 1073741824;
    }

    return $num;
  }

  /**
   * List of system information.
   *
   * @return array    // List of system information
   */
  public function to_array() {
    global $wpdb;
    if (function_exists('curl_version')) {
      $curl_version = curl_version();
    } else {
      $curl_version = [];
    }

    return [
      // WP related.
      'wp_version' => get_bloginfo('version'),
      'wp_site_url' => \site_url(),
      'wp_timezone' => $this->get_timezone(),
      'wp_blog_time' => time(),
      'wp_root_dir' => ABSPATH,
      'wp_language' => get_bloginfo('language'),
      'wp_cache' => defined('WP_CACHE') ? WP_CACHE : null,
      'wp_fs_method' => defined('FS_METHOD') ? FS_METHOD : null,
      'wp_db_charset' => defined('DB_CHARSET') ? DB_CHARSET : null,
      'wp_db_collate' => defined('DB_COLLATE') ? DB_COLLATE : null,
      'wp_debug' => defined('WP_DEBUG') ? WP_DEBUG : null,
      'wp_debug_log' => defined('WP_DEBUG_LOG') ? WP_DEBUG_LOG : null,
      'wp_debug_display' => defined('WP_DEBUG_DISPLAY') ? WP_DEBUG_DISPLAY : null,
      'wp_script_debug' => defined('SCRIPT_DEBUG') ? SCRIPT_DEBUG : null,
      // 'wp_content_dir'                       => File_System::normalize_path( $this->get_content_dir() ),
      // 'wp_plugin_dir'                        => ( new File_System() )->get_plugin_root_directory(),
      // 'wp_theme_dir'                         => ( new File_System() )->get_theme_root_directory(),
      // 'wp_upload_dir'                        => ( new File_System() )->get_upload_directory(),
      'wp_upload_dir_url' => $this->get_upload_dir_url(),
      'wp_multisite_enabled' => $this->check_multisite(),
      'wp_memory_limit_readable' => defined('WP_MEMORY_LIMIT') ? WP_MEMORY_LIMIT : null,
      'wp_memory_limit_bytes' => defined('WP_MEMORY_LIMIT') ? $this->readble_size_to_bytes(WP_MEMORY_LIMIT) : null,
      'wp_max_memory_limit_readble' => defined('WP_MAX_MEMORY_LIMIT') ? WP_MAX_MEMORY_LIMIT : null,
      'wp_max_memory_limit_bytes' => defined('WP_MAX_MEMORY_LIMIT') ? $this->readble_size_to_bytes(WP_MAX_MEMORY_LIMIT) : null,
      'wp_active_plugins_info' => $this->get_active_plugins_info(),
      'wp_alternative_cron_enabled' => defined('ALTERNATE_WP_CRON') ? ALTERNATE_WP_CRON : null,
      'wp_cron_enabled' => defined('DISABLE_WP_CRON') ? false : true,
      'wp_cron_lock_timeout' => defined('WP_CRON_LOCK_TIMEOUT') ? WP_CRON_LOCK_TIMEOUT : null,
      'wp_cron_job_running' => defined('DOING_CRON') ? DOING_CRON : false,
      'wp_http_block_external' => defined('WP_HTTP_BLOCK_EXTERNAL') ? true : false,
      'wp_automatic_update_disable' => defined('AUTOMATIC_UPDATER_DISABLED') ? true : false,
      'wp_active_themes_info' => $this->get_active_themes_info(),

      // Webserver related information.
      'web_server_name' => $this->get_webserver(),
      'operating_system_short_name' => $this->get_os(),
      'operating_system_full' => $this->get_operating_system(),
      'server_ip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : null,
      'temp_folder' => get_temp_dir(),

      // PHP Library related info.

      // Disk & storage related info.
      'disk_free_space_bytes' => $this->get_disk_free_space(),

      'disk_free_space_readable' => (($this->is_enabled('disk_total_space')) ? BMP::humanSize($this->get_disk_free_space()) : __('Blocked by hosting', 'backup-backup')),
      'dir_disk_space_bytes' => (($this->is_enabled('disk_total_space')) ? disk_total_space(ABSPATH) : __('Blocked by hosting', 'backup-backup')),
      'dir_disk_space_readable' => (($this->is_enabled('disk_total_space')) ? BMP::humanSize(disk_total_space(ABSPATH)) : __('Blocked by hosting', 'backup-backup')),

      // PHP Configuration information.
      'php_memory_limit_bytes' => $this->readble_size_to_bytes(ini_get('memory_limit')),
      'php_memory_limit_readable' => ini_get('memory_limit'),
      'php_max_execution_time' => ini_get('max_execution_time'),
      'php_upload_max_filesize_bytes' => $this->readble_size_to_bytes(ini_get('upload_max_filesize')),
      'php_upload_max_filesize_readable' => ini_get('upload_max_filesize'),
      'php_max_input_vars' => (int) ini_get('max_input_vars'),
      'php_post_max_size_bytes' => $this->readble_size_to_bytes(ini_get('post_max_size')),
      'php_post_max_size_readable' => ini_get('post_max_size'),

      'php_version_primary' => $this->get_php_version_primary(),
      'php_version_secondary' => $this->get_php_version_secondary(),
      'php_version_minor' => $this->get_php_version_minor(),
      'php_version_full' => $this->get_php_version(),

      'php_sapi' => php_sapi_name(),
      'php_allow_url_fopen' => ini_get('allow_url_fopen') === 1 ? true : false,
      'php_loaded_extensions' => $this->get_php_loaded_extensions(),
      'php_disable_functions' => $this->get_php_disable_functions(),
      'php_xml_support' => extension_loaded('xml'),
      'php_backtrack_limit' => $this->get_backtrack_limit(),
      'php_zip_archive_class_exists' => class_exists('ZipArchive'),
      'php_mcrypt_exists' => extension_loaded('mcrypt'),
      'open_basedir' => ini_get('open_basedir'),

      // MySql Configuration information.
      'mysql_version' => $wpdb->db_version(),
      'mysql_character_set' => $this->get_mysql_character_set(),

      // Cron related information.
      'cron_shared' => get_option('bmi_cron_new_domain_done', false) ? "shared" : "not_shared",
      'cron_sk' => get_option('bmi_sk_keepalive', false) ? get_option('bmi_sk_keepalive', false) : "not_set",
      'cron_last_ping_time' => get_option('bmi_cron_last_ping_time', false) ? get_option('bmi_cron_last_ping_time', false) : "not_set",
      'cron_site_local_or_unreachable' => get_option('bmi_cron_site_local_or_unreachable', false) ? get_option('bmi_cron_site_local_or_unreachable', false) : "not_set",

      'curl_version' => isset($curl_version['version']) ? $curl_version['version'] : null,
      'curl_ssl_enabled' => isset($curl_version['features']) ? (bool) ($curl_version['features'] & 4) : false,
      'php_open_ssl_version_text' => isset($curl_version['ssl_version']) ? $curl_version['ssl_version'] : null,
      'php_open_ssl_version_number' => isset($curl_version['ssl_version_number']) ? $curl_version['ssl_version_number'] : null,
      'plugin_compile_method' => defined('BMI_REV') ? BMI_REV : 'unknown'
    ];
  }
}
