<?php

namespace CleantalkSP\SpbctWP;

use CleantalkSP\Common\Enqueue\Enqueue;
use CleantalkSP\SpbctWP\Scanner\Helper;
use CleantalkSP\SpbctWP\Scanner\ScannerQueue;
use CleantalkSP\SpbctWP\Variables\Cookie;
use CleantalkSP\SpbctWP\VulnerabilityAlarm\PscCertifiedPluginsController;

class SpbcEnqueue extends Enqueue
{
    protected $plugin_version = SPBC_VERSION;
    protected $assets_path = SPBC_PATH;
    protected $plugin_path = SPBC_PLUGIN_DIR;
    private static $public_localized = false;

    /**
     * @param string $after_script script "handle" name that localization goes after
     * @return void
     */
    private static function localizePublicData($spbc, $after_script)
    {
        if (!self::$public_localized) {
            self::$public_localized = true;
            wp_localize_script(
                $after_script,
                'spbcPublic',
                array (
                    '_ajax_nonce'                          => wp_create_nonce('ct_secret_stuff'),
                    '_rest_nonce'                          => wp_create_nonce('wp_rest'),
                    '_ajax_url'                            => admin_url('admin-ajax.php', 'relative'),
                    '_rest_url'                            => esc_url(get_rest_url()),
                    'data__set_cookies'                    => $spbc->settings['data__set_cookies'],
                    'no_confirm_row_actions'               => Helper::getRowActionsNeedsNoConfirm(),
                )
            );
        }
    }

    /**
     * Register stylesheet and scripts.
     * @psalm-suppress InvalidArgument
     */
    public static function handleEnqueueHook($hook)
    {
        global $spbc;

        // css for all admin pages - includes profile page
        self::getInstance()->css('spbc-admin.css');
        self::getInstance()->css('spbc-icons.css');

        // Profile page handling
        if ($hook === 'profile.php' || $hook === 'user-edit.php') {
            self::handleProfilePages($spbc);
        }

        // If the user is not admin
        if ( ! current_user_can('upload_files')) {
            return;
        }

        self::handleAdminWide($spbc);

        if ($spbc->settings['upload_checker__file_check'] && in_array($hook, array('upload.php', 'media-new.php'))) {
            self::getInstance()->js('spbc-upload.js', array('jquery'));
        }

        // For settings page
        if ($hook === 'settings_page_spbc' || $hook === 'settings_page_spbct') {
            self::handlePluginSettingsPage($spbc);
        }
    }

    /**
     * Enqueue common CSS/JS and localize common data for admin pages.
     * @param State $spbc
     * @return void
     */
    private static function handleAdminWide($spbc)
    {
        // For ALL admin pages
        self::getInstance()->js('spbc-common.js', array('jquery'));
        self::getInstance()->js('spbc-admin.js', array('jquery'));

        $vulnerability_show_install = (
            isset($spbc->settings['vulnerability_check__test_before_install']) &&
            $spbc->settings['vulnerability_check__test_before_install'] == true
        );

        $vulnerability_show_list = (
            isset($spbc->settings['vulnerability_check__enable_cron'], $spbc->settings['vulnerability_check__warn_on_modules_pages']) &&
            $spbc->settings['vulnerability_check__enable_cron'] == true &&
            $spbc->settings['vulnerability_check__warn_on_modules_pages'] == true
        );

        $email = spbc_get_admin_email();
        $website = get_home_url();
        wp_localize_script('spbc-common-js', 'spbcSettings', array(
            'wpms'                            => (int) is_multisite(),
            'is_main_site'                    => (int) is_main_site(),
            'img_path'                        => SPBC_PATH . '/images',
            'key_is_ok'                       => $spbc->key_is_ok,
            'critical'                        => $spbc->data['display_scanner_warnings']['critical'],
            'secfw_enabled'                     => $spbc->settings['secfw__enabled'],
            'ajax_nonce'                      => wp_create_nonce("spbc_secret_nonce"),
            'ajaxurl'                         => admin_url('admin-ajax.php', 'relative'),
            //'debug'        => !empty($debug) ? 1 : 0,
            'key_changed'                     => ! empty($spbc->data['key_changed']),
            'admin_bar__admins_online_counter' => $spbc->settings['admin_bar__admins_online_counter'] ? 1 : 0,
            'needToWhitelist'                 => ! Cookie::get('spbc_secfw_ip_wl'),
            'frontendAnalysisAmount'          => (defined('SPBCT_ALLOW_CURL_SINGLE') && SPBCT_ALLOW_CURL_SINGLE) ? 2 : 20,
            'spbctNoticeDismissSuccess'       => \CleantalkSP\SpbctWP\AdminBannersModule\AdminBannersHandler::getJSONOfPostNotices(),
            'vulnerabilityShowInstall'        => $vulnerability_show_install,
            'vulnerabilityShowList'           => $vulnerability_show_list,
            'spbcSpinner'               => array (
                'imgSource' => SPBC_PATH . '/images/preloader2.gif',
                'altText' => esc_html__('Loading...', 'security-malware-firewall')
            ),
            'wl_mode_enabled' => $spbc->data['wl_mode_enabled'],
            'wl_company_name' => $spbc->data['wl_company_name'],
            'wl_support_url' => $spbc->data['wl_support_url'],
            'wl_support_email' => $spbc->data['wl_support_email'],
            'default_wl_support_url' => $spbc->default_data['wl_support_url'],
            'clear_scan_results' => esc_html__('Clear scan results', 'security-malware-firewall'),
            'clear_results_confirm' => esc_html__('Attention! This action will clear all scan results. Do you confirm?', 'security-malware-firewall'),
            'support_user_creation_msg_array' => SupportUser::getMessages(),
            'link_remove_malware_from_website' => LinkConstructor::buildCleanTalkLink(
                'banner_link_for_treatment',
                'wordpress-malware-removal',
                array(
                    'email' => esc_attr($email),
                    'website' => esc_attr($website),
                ),
                'https://cleantalk.org'
            ),
            'last_sync_date' => $spbc->data['last_sync_date'] ? date('d M Y H:i', $spbc->data['last_sync_date']) : false,
            'sync_in_progress' => ! empty($spbc->data['sync_progress']) && ! empty($spbc->data['sync_progress']['in_progress']),
        ));

        self::getInstance()->js('spbc-cookie.js', array('jquery'));

        self::localizePublicData($spbc, 'spbc-cookie-js');
    }

    /**
     * Enqueue user data pages scripts. This needs to manage 2fa settings on a user-page.
     * @param State $spbc
     * @return void
     */
    private static function handleProfilePages($spbc)
    {
        //css only!
        self::getInstance()->custom(
            'jquery-ui',
            SPBC_PATH . '/css/jquery-ui.min.css',
            array(),
            '1.12.1',
            null,
            'all'
        );
        wp_enqueue_script('jquery-ui-dialog');

        // 2FA required stuff
        $user_obj = wp_get_current_user();
        if (spbc_is_user_role_in($spbc->settings['2fa__roles'], $user_obj)) {
            self::getInstance()->js('spbc-2fa.js', array('jquery'));
            self::localizePublicData($spbc, 'spbc-2fa-js');
        }
    }

    /**
     * Enqueue settings page CSS/JS and localize data for settings page.
     * @return void
     */
    private static function handlePluginSettingsPage($spbc)
    {
        /**
         * ============== SETTINGS CSS SCRIPTS ==============
         */
        self::getInstance()->css('spbc-settings.css');
        self::getInstance()->css('spbc-settings-media.css');
        self::getInstance()->css('spbc-table.css');
        self::getInstance()->css('spbc-timeline-widget.css');
        wp_deregister_style('jquery-ui-style');
        self::getInstance()->custom(
            'jquery-ui',
            SPBC_PATH . '/css/jquery-ui.min.css',
            array(),
            '1.12.1',
            null,
            'all'
        );

        /**
         * ============== SETTINGS JS SCRIPTS ==============
         */

        /**
         * Load default WordPress scripts.
         */
        self::jqAddBuiltIn();

        PscCertifiedPluginsController::maybeEnqueueSettingsAssets();

        /**
         * Load custom SPBCT scripts.
         */

        self::getInstance()->js('spbc-settings.js', array('jquery'), true);
        self::getInstance()->js('spbc-table.js', array('jquery'), true);
        self::getInstance()->js('spbc-scanner-plugin.js', array('jquery'), true);
        self::getInstance()->js('spbc-modal.js', array('jquery'), true);
        self::getInstance()->js('public/spbct-react-bundle.js', array('wp-i18n'), true);
        self::getInstance()->js('spbc-timeline-widget.js');

        wp_set_script_translations('spbct-react-bundle-js', 'security-malware-firewall');


        /**
         * ============== LOCALIZATION FOR JS SCRIPTS ==============
         */

        /**
         * Init vars
         */

        $button_template = '<button %sclass="spbc_scanner_button_file_%s">%s<img class="spbc_preloader_button" src="' . SPBC_PATH . '/images/preloader.gif" /></button>';
        $button_template_send     = sprintf($button_template, '', 'send', __('Send for analysys', 'security-malware-firewall'));
        $button_template_delete   = sprintf($button_template, '', 'delete', __('Delete', 'security-malware-firewall'));
        $button_template_approve  = sprintf($button_template, '', 'approve', __('Approve', 'security-malware-firewall'));
        $button_template_view     = sprintf($button_template, '', 'view', __('View', 'security-malware-firewall'));
        $button_template_view_bad = sprintf($button_template, '', 'view_bad', __('View suspicious code', 'security-malware-firewall'));
        $button_template_replace  = sprintf($button_template, '', 'replace', __('Replace with original', 'security-malware-firewall'));
        $button_template_compare  = sprintf($button_template, '', 'compare', __('Show difference', 'security-malware-firewall'));
        $actions_unknown  = $button_template_send . $button_template_delete . $button_template_approve . $button_template_view;
        $actions_modified = $button_template_approve . $button_template_replace . $button_template_compare . $button_template_view_bad;
        $users_actions = spbc_get_timeline_users_actions();
        // Getting scanner settings
        $scanner_settings = array_filter(
            (array) $spbc->settings,
            function ($key) {
                return strpos($key, 'scanner') === 0;
            },
            ARRAY_FILTER_USE_KEY
        );

        /**
         * Do localize.
         */

        wp_localize_script('spbc-table-js', 'spbcTableLocalize', array(
            'scannerIsActive' => esc_html__('Scanner is active for now. Try later.', 'security-malware-firewall'),
        ));

        wp_localize_script('spbc-settings-js', 'spbcSettingsSecLogs', array(
            'amount' => SPBC_LAST_ACTIONS_TO_VIEW,
            'clicks' => 0,
            'autoClicks' => 0,
        ));

        wp_localize_script('spbc-settings-js', 'spbcSettingsFWLogs', array(
            'moderate' => $spbc->moderate ? 1 : 0,
            'amount'   => SPBC_LAST_ACTIONS_TO_VIEW,
            'clicks'   => 0,
        ));

        wp_localize_script('spbc-settings-js', 'spbcTable', array(
            'warning_bulk'       => __('Are sure you want to perform these actions?', 'security-malware-firewall'),

            'warning_default'    => __('Do you want to proceed?', 'security-malware-firewall'),

            'warning_h_approve'    => __('Do you want to approve this file?', 'security-malware-firewall'),
            'warning_t_approve'    => __('If you agree, this file will be approved.', 'security-malware-firewall'),

            'warning_h_send'       => __('Do you want to proceed?', 'security-malware-firewall'),
            'warning_t_send'    => __('This file will be sent to the Cloud to analyze for a malware, usually processing takes up to 1 minute. The result will be shown in the Analysis log.', 'security-malware-firewall'),

            'warning_h_delete'      => __('This can\'t be undone and could damage your website. Are you sure?', 'security-malware-firewall'),
            'warning_t_delete'    => __('If you agree, this file will be deleted.', 'security-malware-firewall'),

            'warning_h_delete_quarantine' => __('Delete the quarantined copy? This can\'t be undone.', 'security-malware-firewall'),
            'warning_t_delete_quarantine' => __('The quarantined copy of this file will be permanently deleted from the quarantine storage. Your live website files will not be affected.', 'security-malware-firewall'),

            'warning_h_replace'    => __('This can\'t be undone. Are you sure?', 'security-malware-firewall'),
            'warning_t_replace'    => __('If you agree, this file will be replaced.', 'security-malware-firewall'),

            'warning_h_quarantine' => __('This could damage your website, but you will have an option to restore the file.', 'security-malware-firewall'),
            'warning_t_quarantine'    => __('If you agree, this file will be quarantined.', 'security-malware-firewall'),
        ));

        wp_localize_script('spbc-settings-js', 'spbcScaner', array(

            // PARAMS
            'settings'                            => $scanner_settings,
            'states'                              => ScannerQueue::$stages,
            'timezone_shift'                            => $spbc->data['site_utc_offset_in_seconds'] ?: false,

            // Settings / Statuses
            'scaner_enabled'                      => $spbc->scaner_enabled ? 1 : 0,
            'check_links'                         => $spbc->settings['scanner__outbound_links'] ? 1 : 0,
            'check_heuristic'                     => $spbc->settings['scanner__heuristic_analysis'] ? 1 : 0,
            'check_signature'                     => $spbc->settings['scanner__signature_analysis'] ? 1 : 0,
            'check_binary'                        => $spbc->settings['scanner__binary_analysis'] ? 1 : 0,
            'auto_cure'                           => $spbc->settings['scanner__auto_cure'] ? 1 : 0,
            'check_frontend'                      => $spbc->settings['scanner__frontend_analysis'] ? 1 : 0,
            'check_listing'                       => $spbc->settings['scanner__important_files_listing'] ? 1 : 0,
            'wp_content_dir'                      => realpath(WP_CONTENT_DIR),
            'wp_root_dir'                         => realpath(ABSPATH),

            // Templates
            'row_template'                        => '<tr type="%s" class="spbc_scan_result_row" file_id="%s"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>',
            'row_template_links'                  => '<tr class="spbc_scan_result_row"><td><a href=%s target="_blank">%s</a></td><td><a href=%s target="_blank">%s</a></td><td>%s</td></tr>',
            'actions_unknown'                     => $actions_unknown,
            'actions_modified'                    => $actions_modified,
            'page_selector_template'              => '<li class="pagination"><a href="#" class="spbc_page" type="%s" page="%s"><span%s>%s</span></a></li>',

            //TRANSLATIONS

            //Confirmation
            'scan_modified_confiramation'         => __('There is more than 30 modified files and this could take time. Do you want to proceed?', 'security-malware-firewall'),
            'warning_about_cancel'                => __('Scan will be performed in the background mode soon.', 'security-malware-firewall'),
            'delete_warning'                      => __('Are you sure you want to delete the file? It can not be undone.'),
            // Buttons
            'button_scan_perform'                 => __('Perform Scan', 'security-malware-firewall'),
            'button_scan_pause'                   => __('Pause scan', 'security-malware-firewall'),
            'button_scan_resume'                  => __('Resume scan', 'security-malware-firewall'),
            // Progress bar
            'progressbar_get_cms_hashes'          => __('Receiving hashes', 'security-malware-firewall'),
            'progressbar_get_modules_hashes'      => __('Receiving plugins hashes', 'security-malware-firewall'),
            'progressbar_get_approved_hashes'     => __('Updating statuses for the approved files', 'security-malware-firewall'),
            'progressbar_get_denied_hashes'       => __('Updating statuses for the denied files', 'security-malware-firewall'),
            'progressbar_clean_results'           => __('Preparing', 'security-malware-firewall'),
            // Scanning core
            'progressbar_file_system_analysis'    => __('Scanning for modifications', 'security-malware-firewall'),
            'progressbar_heuristic_analysis'      => __('Heuristic analysis', 'security-malware-firewall'),
            'progressbar_schedule_send_heuristic_suspicious_files'      => __('Schedule suspicious files to be automatically sent for analysis', 'security-malware-firewall'),
            'progressbar_signature_analysis'      => __('Searching for signatures', 'security-malware-firewall'),
            'progressbar_binary_analysis'         => __('Binary files analysis', 'security-malware-firewall'),
            //Cure
            'progressbar_auto_cure_backup'        => __('Creating a backup', 'security-malware-firewall'),
            'progressbar_auto_cure'               => __('Cure', 'security-malware-firewall'),
            //OS Cron
            'progressbar_os_cron_analysis'               => __('Cron tasks analysis', 'security-malware-firewall'),
            //DB triggers
            'progressbar_db_trigger_analysis'               => __('DB Trigger analysis', 'security-malware-firewall'),
            // Links
            'progressbar_outbound_links'          => __('Scanning links', 'security-malware-firewall'),
            // Frontend
            'progressbar_frontend_analysis'       => __('Scanning pages', 'security-malware-firewall'),
            // Other
            'progressbar_important_files_listing' => __('Check pages for listing', 'security-malware-firewall'),
            'progressbar_send_results'            => __('Sending results', 'security-malware-firewall'),
            // Warnings
            'result_text_bad_template'            => __('Recommend to scan all (%s) of the found files to make sure the website is secure.', 'security-malware-firewall'),
            'result_text_good_template'           => __('No threats are found.', 'security-malware-firewall'),
            //Misc
            'look_below_for_scan_res'             => __('Look below for scan results.', 'security-malware-firewall'),
            'view_all_results'                    => sprintf(
                __('</br>%sView all scan results for this website%s', 'security-malware-firewall'),
                '<a target="blank" href="https://cleantalk.org/my/logs_mscan?service=' . $spbc->service_id . '">',
                '</a>'
            ),
            'last_scan_was_just_now'              => __('The last scan of this website happened just now. Files scanned: %s.', 'security-malware-firewall'),
            'last_scan_was_just_now_links'        => __('The last scan of this website happened just now. Files scanned: %s. Outbound links found: %s.', 'security-malware-firewall'),
            'copy_log_to_clipboard_hint'         => __('Copied!', 'security-malware-firewall'),
            'copy_log_to_clipboard_hint_failed'  => __('Failed to copy!', 'security-malware-firewall'),
            'copy_log_to_clipboard_hint_unsupported'  => __('Clipboard API not supported in local environment', 'security-malware-firewall'),
        ));

        wp_localize_script('spbc-settings-js', 'spbcDescriptions', array(
            'waf__enabled'                => __('Bla bla', 'security-malware-firewall'),
            'waf__xss_check'              => __('Cross-Site Scripting (XSS) — prevents malicious code to be executed/sent to any user. As a result malicious scripts can not get access to the cookie files, session tokens and any other confidential information browsers use and store. Such scripts can even overwrite content of HTML pages. CleanTalk WAF monitors for patterns of these parameters and block them.', 'security-malware-firewall'),
            'waf__sql_check'              => __('SQL Injection — one of the most popular ways to hack websites and programs that work with databases. It is based on injection of a custom SQL code into database queries. It could transmit data through GET, POST requests or cookie files in an SQL code. If a website is vulnerable and execute such injections then it would allow attackers to apply changes to the website\'s MySQL database.', 'security-malware-firewall'),
            'upload_checker__file_check'  => __('The option checks each uploaded file to a website for malicious code. If it\'s possible for visitors to upload files to a website, for instance a work resume, then attackers could abuse it and upload an infected file to execute it later and get access to your website.', 'security-malware-firewall'),
            'traffic_control__enabled'    => __('It analyzes quantity of requests towards website from any IP address for a certain period of time. For example, for an ordinary visitor it\'s impossible to generate 2000 requests within 1 hour. Big amount of requests towards website from the same IP address indicates that there is a high chance of presence of a malicious program.', 'security-malware-firewall'),
            'scanner__outbound_links'     => __('This option allows you to know the number of outgoing links on your website and website addresses they lead to. The option\'s purpose is to check your website and find hidden, forgotten and spam links. You should always remember if you have links to other websites which have a bad reputation, it could affect your visitors\' trust and your SEO.', 'security-malware-firewall'),
            'scanner__heuristic_analysis' => __('Often, authors of malicious code disguise their code which makes it difficult to identify it by their signatures. The malicious code itself can be placed anywhere on the site, for example the obfuscated PHP-code in the "logo.png" file, and the code itself is called by one inconspicuous line in "index.php". Therefore, the usage of plugins to search for malicious code is preferable. Heuristic analysis can indicate suspicious PHP constructions in a file that you should pay attention to.', 'security-malware-firewall'),
            'scanner__signature_analysis' => __('Code signatures — it\'s a code sequence a malicious program consists of. Signatures are being added to the database after analysis of the infected files. Search for such malicious code sequences is performed in scanning by signatures. If any part of code matches a virus code from the database, such files would be marked as critical.', 'security-malware-firewall'),
            'scanner__auto_cure'          => __('It cures infected files automatically if the scanner knows cure methods for these specific cases. If the option is disabled then when the scanning process ends you will be presented with several actions you can do to the found files: Cure. Malicious code will be removed from the file. Replace. The file will be replaced with the original file. Delete. The file will be put in quarantine. Do nothing. Before any action is chosen, backups of the files will be created and if the cure is unsuccessful it\'s possible to restore each file.', 'security-malware-firewall'),
            'misc__backend_logs_enable'   => __('To control appearing errors you have to check log file of your hosting account regularly. It\'s inconvenient and just a few webmasters pay attention to it. Also, errors could appear for a short period of time and only when one specific function is running, they can\'t be spotted in other circumstances so it\'s hard to catch them. PHP errors tell you that some of your website functionality doesn\'t work correctly, furthermore hackers may use these errors to get access to your website. The CleanTalk Scanner will check your website backend once per hour. Statistics of errors is available in your CleanTalk Dashboard.', 'security-malware-firewall'),
            'data__set_cookies'           => __('Part of the CleanTalk FireWall functions depend on cookie files, so disabling this option could lead to deceleration of the firewall work. It will affect user identification who are logged in right now. Traffic Control will not be able to determine authorized users and they could be blocked when the request limit is reached. We do not recommend to disable this option without serious reasons. However, you should disable this option is you\'re using Varnish.', 'security-malware-firewall'),
            '2fa__enable'                 => __('Two-Factor Authentication for WordPress admin accounts will improve your website security and make it safer, if not impossible, for hackers to breach your WordPress account. Two-Factor Authentication works via e-mail. Authentication code will be sent to your admin email. When authorizing, a one-time code will be sent to your email. While entering the code, make sure that it does not contain spaces. With your first authorization, the CleanTalk Security plugin remembers your browser and you won’t have to input your authorization code every time anymore. However, if you started to use a new device or a new browser then you are required to input your authorization code. The plugin will remember your browser for 30 days.', 'security-malware-firewall'),
        ));

        wp_localize_script('spbc-timeline-widget-js', 'spbcTimelineWidgetData', $users_actions);
    }

    /**
     * Handle script tags with some attributes (ex. defer/async)
     * @param string $tag
     * @param string $handle
     *
     * @psalm-suppress PossiblyUnusedReturnValue
     * @return string
     */
    public static function addScriptAttributes($tag, $handle)
    {
        $async_scripts = array(
            'spbc-scannerplugin-js',
            'spbc-scaner-events-js',
            'spbc-scaner-callbacks-js',
        );

        $defer_scripts = array(
            'spbc-settings-js',
            'spbc-scaner-js',
        );

        if (in_array($handle, $async_scripts)) {
            return str_replace(' src', ' async="async" src', $tag);
        } elseif (in_array($handle, $defer_scripts)) {
            return str_replace(' src', ' defer="defer" src', $tag);
        } else {
            return $tag;
        }
    }

    /**
     * Enqueue built in jQuery source from WordPress src
     * @return void
     */
    private static function jqAddBuiltIn()
    {
        wp_enqueue_script('jquery-ui-core');
        wp_enqueue_script('jquery-ui-progressbar');
        wp_enqueue_script('jquery-ui-accordion');
        wp_enqueue_script('jquery-ui-resizable');
        wp_enqueue_script('jquery-ui-dialog');
    }

    /**
     * @param string $error
     *
     * @return void
     */
    public static function errorWrite($error)
    {
        SpbcDevLogger::write($error);
    }
}
