<?php
/*
Plugin Name: Signteer
Plugin URI: https://www.signteer.com/
Description: A volunteer sign-up sheets plugin to let your volunteers sign up for your tasks.
Version: 1.0.5
Author: plainware
Author URI: https://www.plainware.com/
License: GPLv2 or later
*/

namespace Signteer;

if (!defined('ABSPATH')) {
    exit;
}

if (file_exists(__DIR__ . '/fs.php')) {
    require __DIR__ . '/fs.php';
}

class Plugin
{
    private string $slug = 'sgntr';
    private string $dbPrefix = 'signteer';
    private string $pluginFile;
    private string $restRouteNamespace = 'signteer/v1';
    private $app;
    private $response = null;

    public static function start(): self
    {
        return new static(__FILE__);
    }

    public static function uninstall()
    {
        $instance = static::start();

        $instance->bootCore();
        $migrator = $instance->app->make(\Plainwork\Database\Migrator::class);
        $installed = $migrator->isInstalled();
        if ($installed) {
            $migrator->down();
        }
    }

    public function __construct(string $pluginFile)
    {
        $this->pluginFile = $pluginFile;

        add_action('admin_menu', [$this, 'adminMenu'] );
        add_action('admin_init', [$this, 'adminInit'] );
        add_action('wp_ajax_' . $this->slug, [$this, 'adminAjax']);

        add_action('rest_api_init', [$this, 'wpRestInit']);

        add_action('init', [$this, 'registerPostTypes']);
        add_action('template_redirect', [$this, 'partialCustomPost']);
        add_action('the_content', [$this, 'renderCustomPost']);
    }

    public function adminMenu()
    {
        $label = 'Signteer';
        $cap = 'manage_options';
        $icon = 'dashicons-list-view';
        $pos = 5;
        add_menu_page($label, $label, $cap, $this->slug, [$this, 'render'], $icon, $pos);
    }

    public function registerPostTypes()
    {
        include_once __DIR__ . '/app/src/Core/WordPress/SheetPostType.php';
        namespace\Core\WordPress\SheetPostType::register();
    }

    public function partialCustomPost()
    {
    // has layout param? used for ajax partials, print views, downloads
        if (!$this->hasLayoutParam()) {
            return;
        }

        $content = $this->getCustomPostContent();
        if (strlen($content)) {
            $this->render();
            exit;
        }
    }

    private function getCustomPostContent(): string
    {
        $ret = '';

        $postType = namespace\Core\WordPress\SheetPostType::POST_TYPE;
        if (!is_singular($postType)) {
            return $ret;
        }

        $wpPostId = get_the_ID();

        return $this->runWeb('front/sheet/' . $wpPostId);
    }

    public function renderCustomPost($ret)
    {
        $content = $this->getCustomPostContent();
        if (!strlen($content)) {
            return $ret;
        }

        return $ret . wp_kses($content, $this->allowedTags());
    }

    public function wpRestInit()
    {
        register_rest_route($this->restRouteNamespace, '/sheets/(?P<id>\d+)/tasks',
            [
                'methods' => \WP_REST_Server::READABLE,
                'callback' => [$this, 'restHandle'],
                'permission_callback' => '__return_true',
            ],
        );
    }

    public function restHandle(\WP_REST_Request $wpRestRequest)
    {
        $this->bootRest();
        $server = $this->app->make(\Plainwork\HttpWordPress\WordPressServer::class);

        return $server->handleWpRestRequest($wpRestRequest, $this->restRouteNamespace, 'api');
    }

    private function bootCore()
    {
        if ($this->app) {
            return;
        }

    /* dev? */
        $isDev = false;
        $f = __DIR__ . '/dev.php';
        if (file_exists($f)) {
            $isDev = true;
            require $f;
        }

    /* autoload */
        require __DIR__ . '/app/autoload.php';

    /* initiate the app */
        $env = [];
        $app = new \Plainwork\Core\App(__FILE__, $env);

    // database prefix
        $myDbPrefix = $this->dbPrefix;

        global $wpdb;
        if (is_multisite()) {
            // $shareDatabase = get_site_option( 'plaineventcalendar_share_database', 0 );
            $shareDatabase = false;
            $wpdbPrefix = $shareDatabase ? $wpdb->base_prefix : $wpdb->prefix;
        } else {
            $wpdbPrefix = $wpdb->prefix;
        }
        $dbPrefix = $wpdbPrefix . $myDbPrefix . '_';

    // db prefix
        $app->onBoot(\Plainwork\Database\Database::class, fn($db) => $db->setPrefix($dbPrefix));

    /* boot */
        if ($isDev) {
            new \Plainwork\Dev\Boot($app);
        }

        new WordPressBoot($app);
        if (class_exists(ProBoot::class)) {
            new ProBoot($app);
        }

    /* ready */
        $this->app = $app;
    }

    private function bootRest()
    {
        $this->bootCore();
    }

    private function bootWeb()
    {
        $this->bootCore();

    // request prefix
        $prefix = $this->slug;
        $this->app->onBoot(\Plainwork\Http\Server::class, fn($server) => $server->setPrefix($prefix));

    // uri href func
        $this->app->onBoot(\Plainwork\Http\Uri::class,
            function ($uri) {
                $uri
                    ->addHrefFunc([$this, 'uriHref'])
                    ->addAssetFunc([$this, 'uriAsset'])
                    ;
            });
    }

    private function runWeb(string $rootPath = ''): string
    {
        if (null === $this->response) {
            $this->bootWeb();
            $server = $this->app->make(\Plainwork\Http\Server::class);
            $this->response = $server->run($rootPath);
        }

        return $this->response;
    }

    public function adminInit()
    {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $wpAdminPage = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';

    // our page?
        if ($this->slug != $wpAdminPage) {
            return;
        }

        $this->runWeb();

    // has layout param? used for ajax partials, print views, downloads
        if ($this->hasLayoutParam()) {
            $this->render();
            exit;
        }
    }

    public function adminAjax()
    {
        $this->render();
        wp_die();
    }

    public function uriHref(array $params)
    {
        if (is_admin()) {
            $ret = 'admin.php?page=' . $this->slug;
            if ($params) {
                $ret .= '&' . http_build_query($params);
            }
        } else {
            global $post;
            if ($post) {
                $ret = get_permalink($post->ID);
                foreach ($params as $k => $v) {
                    $ret = add_query_arg($k, $v, $ret);
                }
            } else {
                $ret = '';
                if ($params) {
                    $ret .= '?' . http_build_query($params);
                }
            }
        }

        return $ret;
    }

    public function uriAsset($file)
    {
        return plugins_url('app/' . $file, $this->pluginFile);
    }

    private function allowedTags(): array
    {
        return \Plainwork\UiWordPress\Html::allowedTags();
    }

    public function render()
    {
        echo wp_kses($this->runWeb(), $this->allowedTags());
    }

    private function hasLayoutParam(): bool
    {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
        return isset($_GET[$this->slug . 'layout-']) ? true : false;
    }
}

if (function_exists('add_action')) {
    add_action('plugins_loaded', [Plugin::class, 'start']);
}

if (function_exists('register_uninstall_hook')) {
    register_uninstall_hook(__FILE__, [Plugin::class, 'uninstall']);
}
