<?php

namespace CleantalkSP\SpbctWP\FSWatcher;

use CleantalkSP\SpbctWP\FSWatcher\Dto\FSWatcherParams;
use CleantalkSP\SpbctWP\FSWatcher\Scan\Scan;
use CleantalkSP\SpbctWP\FSWatcher\Analyzer\Analyzer;
use CleantalkSP\Variables\Post;

class Controller
{
    /**
     * @var bool
     */
    public static $debug;

    const STATUS_STOPPED = 'stopped';

    const STATUS_RUNNING = 'running';

    /**
     * @var \CleantalkSP\SpbctWP\FSWatcher\Storage\FileStorage::class
     */
    public static $storage;

    private static $status = self::STATUS_STOPPED;

    /**
     * @var FSWatcherParams
     */
    private static $params;

    public function __construct(FSWatcherParams $params)
    {
        self::$params = $params;
        $is_fs_watcher_action = Post::getString('action') === 'spbct_fswatcher_compare' ||
            Post::getString('action') === 'spbct_fswatcher_view_file' ||
            Post::getString('action') === 'spbct_fswatcher_create_snapshot';

        if ( defined('DOING_AJAX') && DOING_AJAX && $is_fs_watcher_action) {
            $this->checkRateLimit();
        }
        add_action('wp_ajax_spbct_fswatcher_compare', [$this, 'ajaxCompare']);
        add_action('wp_ajax_spbct_fswatcher_view_file', [$this, 'ajaxViewFile']);
        add_action('wp_ajax_spbct_fswatcher_create_snapshot', [$this, 'ajaxCreateSnapshot']);
    }

    /**
     * @return Controller self
     */
    public static function getInstance()
    {
        $fswatcher_params = new FSWatcherParams();
        $fswatcher_params->dir_to_watch = ABSPATH;
        $fswatcher_params->exclude_dirs = [];
        $fswatcher_params->extensions_to_watch = ['php'];
        $fswatcher = new self($fswatcher_params);
        $fswatcher::prepareStorage();
        return $fswatcher;
    }

    /**
     * Initialize the `$debug` property false|true
     *
     * @return void
     */
    private static function getDebugState()
    {
        if ( defined('SPBC_FSWATCHER_DEBUG') ) {
            self::$debug = (bool) SPBC_FSWATCHER_DEBUG;
        }
    }

    /**
     * Create snapshot main inner logic.
     *
     * @return void
     */
    public static function createSnapshot()
    {
        self::$status = self::STATUS_RUNNING;
        Scan::run(self::$params);
        self::stop();
    }

    /**
     * Preparing storage.
     *
     * @param $params
     * @return void
     */
    public static function prepareStorage()
    {
        global $spbc;
        self::getDebugState();

        if (self::$debug) {
            Logger::setSaltValue($spbc->data['salt']);
        }

        Service::setStorage(self::$params->storage);
    }

    /**
     * Scanning file system stop trigger
     *
     * @return void
     */
    private static function stop()
    {
        self::$status = self::STATUS_STOPPED;
        Service::setAllJournalsAsCompleted();
    }

    private function checkRateLimit()
    {
        if ( ! Service::rateLimitPassed() ) {
            echo json_encode(array('error' => 'Rate limit exceeded. Protected - Security by CleanTalk.'));
            die();
        }
    }

    public static function ajaxCompare()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');
        if (self::$debug) {
            Logger::log('run compare file system logs');
        }
        $compare_result = Analyzer::getCompareResult();
        header('Content-Type: application/json');
        if (false === $compare_result) {
            if (self::$debug) {
                Logger::log('Can not compare logs');
            }
            echo json_encode(array('error' => 'Can not compare logs'));
        } else {
            echo json_encode($compare_result);
        }
        die();
    }

    public function ajaxViewFile()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');
        if (self::$debug) {
            Logger::log('run view file method');
        }

        header('Content-Type: application/json');
        try {
            $view_file = Analyzer::getViewFile();
            echo json_encode(array("data" => $view_file));
        } catch (\Exception $e) {
            if (self::$debug) {
                Logger::log('Can not view file');
            }
            echo json_encode(array('error' => 'Can not view file. ' . $e->getMessage()));
        }
        die();
    }

    /**
     * Ajax handler. Creating snap call.
     * @return void
     */
    public function ajaxCreateSnapshot()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');
        if (self::$debug) {
            Logger::log('run scan file system');
        }
        self::createSnapshot();
        header('Content-Type: application/json');
        die(json_encode(['OK']));
    }
}
