<?php
/**
 * Base Module (minimum support version)
 * @author arcturus (https://info.drk.st/about contact@drk.st)
 */

include_once __DIR__ . "/event.php";

class EventHandler
{
  /**
   * ... gnuboard5 plugin and skin compatible code ...
   * event list 참고용으로 사용하셔도 됩니다.
   * gnuboard5의 run_event 를 대체하는 함수로 기존 run_event 를 호출하기 위해 선언되어 있는 이름-값 배열입니다.
   * @var string[]
   */
  protected static $gnuboardCompatibleList = [
    // adm/editor_font.php
    "amber.admin.editor_font_form_before"                     => "", // amber only
    "amber.admin.editor_font_form_after"                      => "", // amber only
    // adm/editor_font_update.php
    "amber.admin.editor_font_update_before"                   => "", // amber only
    "amber.admin.editor_font_update_after"                    => "", // amber only
    // common.php
    "gnuboard.loadlibs.after"                                 => "", // amber only
    "gnuboard.htmlprocess.before"                             => "common_header",
    "gnuboard.htmlprocess.after"                              => "", // amber only
    // head.php
    "gnuboard.head.before"                                    => "pre_head",
    // tail.php
    "gnuboard.tail.before"                                    => "", // amber only
    "gnuboard.tail.after"                                     => "", // amber only
    // tail.sub.php
    "gnuboard.tail_sub"                                       => "tail_sub",
    // adm/_common.php
    "gnuboard.admin.load_common"                              => "admin_common",
    // adm/board_copy_update.php
    "gnuboard.admin.board_copy_file"                          => "admin_board_copy_file",
    // adm/board_form_update.php
    "gnuboard.admin.board_form_update"                        => "admin_board_form_update",
    // adm/board_form_before.php
    "gnuboard.admin.board_form_before"                        => "adm_board_form_before",
    // adm/board_list_update.php
    "gnuboard.admin.board_list_update"                        => "admin_board_list_update",
    // adm/boardgroup_form_update.php
    "gnuboard.admin.boardgroup_form_update"                   => "admin_boardgroup_form_update",
    // adm/boardgroup_list_update.php
    "gnuboard.admin.boardgroup_list_update"                   => "admin_boardgroup_list_update",
    // adm/cache_file_delete.php
    "gnuboard.admin.cache_file_delete_before"                 => "adm_cache_file_delete_before",
    "gnuboard.admin.cache_file_delete"                        => "adm_cache_file_delete",
    // adm/config_form_update.php
    "gnuboard.admin.config_form_update"                       => "admin_config_form_update",
    // adm/contentformupdate.php
    "gnuboard.admin.content_created"                          => "admin_content_created",
    "gnuboard.admin.content_updated"                          => "admin_content_updated",
    "gnuboard.admin.content_deleted"                          => "admin_content_deleted",
    // adm/member_form_update.php
    "gnuboard.admin.member_form_update"                       => "admin_member_form_update",
    // adm/member_form.php
    "gnuboard.admin.member_form_add"                          => "admin_member_form_add",
    "gnuboard.admin.member_form_after"                        => "admin_member_form_after",
    // adm/member_list_update.php
    "gnuboard.admin.member_list_update"                       => "admin_member_list_update",
    // adm/menu_list_update.php
    "gnuboard.admin.menu_list_update"                         => "admin_menu_list_update",
    // adm/theme_update.php
    "gnuboard.admin.theme_update"                             => "adm_theme_update",
    // adm/viewer_form_update.php
    "gnuboard.admin.viewer_update"                            => "", // amber only
    // bbs/delete_all.php
    "gnuboard.bbs.delete_all"                                 => "bbs_delete_all",
    // bbs/delete_comment.php
    "gnuboard.bbs.delete_comment"                             => "bbs_delete_comment",
    // bbs/delete.php
    "gnuboard.bbs.delete"                                     => "bbs_delete",
    // bbs/download.php
    "gnuboard.bbs.download_file_header"                       => "download_file_header",
    // bbs/good.php
    "gnuboard.bbs.good_before"                                => "bbs_good_before",
    "gnuboard.bbs.increase_good_json"                         => "bbs_increase_good_json",
    "gnuboard.bbs.increase_good_html"                         => "bbs_increase_good_html",
    "gnuboard.bbs.good_after"                                 => "bbs_good_after",
    // bbs/login_check.php
    "gnuboard.member.login_check_before"                      => "member_login_check_before",
    "gnuboard.member.login_session_before"                    => "login_session_before",
    "gnuboard.member.login_check"                             => "member_login_check",
    // bbs/login.php
    "gnuboard.member.login_tail"                              => "member_login_tail",
    // bbs/logout.php
    "gnuboard.member.logout"                                  => "member_logout",
    // bbs/member_leave.php
    "gnuboard.member.leave"                                   => "member_leave",
    // bbs/memo_delete.php
    "gnuboard.memo.delete"                                    => "memo_delete",
    // bbs/memo_form_update.php
    "gnuboard.memo.form_update_before"                        => "memo_form_update_before",
    "gnuboard.memo.form_update_after"                         => "memo_form_update_after",
    "gnuboard.memo.form_update_failed"                        => "memo_form_update_failed",
    // bbs/memo.php
    "gnuboard.memo.list"                                      => "memo_list",
    // bbs/move_update.php
    "gnuboard.bbs.move_copy"                                  => "bbs_move_copy",
    "gnuboard.bbs.move_update"                                => "bbs_move_update",
    // bbs/move.php
    "gnuboard.bbs.move_html_footer"                           => "move_html_footer",
    // bbs/new_delete.php
    "gnuboard.bbs.new_delete"                                 => "bbs_new_delete",
    // bbs/password_check.php
    "gnuboard.member.password_is_wrong"                       => "password_is_wrong",
    // bbs/password_lost_certify.php
    "gnuboard.member.password_lost_certify_before"            => "password_lost_certify_before",
    "gnuboard.member.password_lost_certify_after"             => "password_lost_certify_after",
    // bbs/password_lost2.php
    "gnuboard.member.password_lost2_after"                    => "password_lost2_after",
    // bbs/qadelete.php
    "gnuboard.bbs.qa_delete"                                  => "qa_delete",
    // bbs/qadownload.php
    "gnuboard.bbs.qa_download_file_header"                    => "qa_download_file_header",
    // bbs/qawrite_update.php
    "gnuboard.bbs.qawrite_update"                             => "qawrite_update",
    // bbs/register_form_update.php
    "gnuboard.member.register_form_update_before"             => "register_form_update_before",
    "gnuboard.member.register_form_update_valid"              => "register_form_update_valid",
    "gnuboard.member.register_form_update_send_mb_mail"       => "register_form_update_send_mb_mail",
    "gnuboard.member.register_form_update_send_admin_mail"    => "register_form_update_send_admin_mail",
    "gnuboard.member.register_form_update_send_certify_mail"  => "register_form_update_send_certify_mail",
    "gnuboard.member.register_form_update_after"              => "register_form_update_after",
    // bbs/register_form.php
    "gnuboard.member.register_form_before"                    => "register_form_before",
    "gnuboard.member.register_form_after"                     => "register_form_after",
    // bbs/write_comment_update.php
    "gnuboard.bbs.comment_update_after"                       => "comment_update_after",
    // bbs/write_update.php
    "gnuboard.bbs.write_update_before"                        => "write_update_before",
    "gnuboard.bbs.write_update_document_create"               => "", // amber only
    "gnuboard.bbs.write_update_document_update"               => "", // amber only
    "gnuboard.bbs.write_update_file_insert"                   => "write_update_file_insert",
    "gnuboard.bbs.write_update_after"                         => "write_update_after",
    // bbs/write.php
    "gnuboard.bbs.write"                                      => "bbs_write",
    // lib/cache.lib.php
    "gnuboard.set_cache_event"                                => "g5_set_cache_event",
    "gnuboard.admin.cache_delete"                             => "adm_cache_delete",
    // lib/common.lib.php
    "gnuboard.goto_url"                                       => "goto_url",
    "gnuboard.alert"                                          => "alert",
    "gnuboard.alert_close"                                    => "alert_close",
    "gnuboard.html_purifier_config"                           => "html_purifier_config",
    "gnuboard.sql_query_after"                                => "sql_query_after",
    "gnuboard.delete_cache_latest"                            => "delete_cache_latest",
    "gnuboard.delete_editor_thumbnail_before"                 => "delete_editor_thumbnail_before",
    "gnuboard.delete_editor_thumbnail_after"                  => "delete_editor_thumbnail_after",
    "gnuboard.member_delete_after"                            => "member_delete_after",
    // lib/mailer.lib.php
    "gnuboard.mail_send_result"                               => "mail_send_result",
    // lib/thumbnail.lib.php
    "gnuboard.is_animated_gif_after"                          => "is_animated_gif_after",
    // plugin/editor/cheditor5/imageUpload/upload.php
    "gnuboard.cheditor_photo_upload"                          => "cheditor_photo_upload",
    // plugin/editor/smarteditor2/photo_uploader/popup/php/index.php
    "gnuboard.smarteditor_photo_upload"                       => "smarteditor_photo_upload",
    // plugin/editor/cheditor5/imageUpload/delete.php
    // plugin/editor/smarteditor2/photo_uploader/popup/php/UploadHandler.php
    "gnuboard.delete_editor_file"                             => "delete_editor_file",
  ];

  /**
   * Summary of eventHandlers
   * @var Event[][]
   */
  protected static $eventHandlers = [];
  protected static $performanceStopwatch = [];
  
  /**
   * script build start time of gnuboard5
   * @var float
   */
  protected static $createdAt;

  public function __construct()
  {
    $this->createdAt = microtime(true);
  }

  protected static function addStopwatch($key)
  {
    if (defined("__IS_DEBUG__")) {
      if (count(self::$performanceStopwatch) > 0) {
        $prev = end(self::$performanceStopwatch);
        self::$performanceStopwatch[$key] = microtime(true) - self::$createdAt - $prev;
      } else {
        self::$performanceStopwatch[$key] = microtime(true) - self::$createdAt;
      }
    }
  }

  public static function addStopwatchWithCallStack($key)
  {
    if (defined("__IS_DEBUG__")) {
      if ($key === 0)
        $key = "start";
      else if ($key === 1)
        $key = "end";
      $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
      $cf = $backtrace[1]['function'] ? $backtrace[1]['function'] : 'global scope';
      self::addStopwatch("{$cf} {$key}");
    }
  }

  /**
   * Adding Custom Functions at the declared time
   * @param string $event : event list 참조
   * @param Event $callback
   * @param int $priority : optional
   * @return void
   */
  public static function addEventHandler($event, $callback, $priority = 10)
  {
    if (!isset(self::$eventHandlers[$event])) {
      self::$eventHandlers[$event] = [];
    }
    self::$eventHandlers[$event][] = new Event($callback, $priority);
  }

  public static function triggerEvent($event, ...$data)
  {
    if (isset(self::$eventHandlers[$event])) {
      foreach (self::$eventHandlers[$event] as $callback) {
        $callback->getAction($data);
      }

      if (function_exists("run_event")) {
        self::gnuboardCompatibleRunEvent($event, $data);
      }
    }
  }

  protected static function gnuboardCompatibleRunEvent($event, $data)
  {
    if (array_key_exists($event, self::$gnuboardCompatibleList) && self::$gnuboardCompatibleList[$event] != "") {
      $compatibleEvent = self::$gnuboardCompatibleList[$event];
      run_event($compatibleEvent, ...$data);
    }
  }
}
