<?php

class BrizyPro_Admin_WhiteLabel
{

    const KEY = 'brizy-white-label';
    const WL_SESSION_KEY = 'brizy-white-label-enabled';

    /**
     * @var string[]
     */
    private $values;

    /**
     * @return BrizyPro_Admin_WhiteLabel
     */
    public static function _init()
    {

        static $instance;

        return $instance ? $instance : $instance = new self();
    }

    /**
     * BrizyPro_Admin_WhiteLabel constructor.
     */
    private function __construct()
    {

        add_action('admin_init', array($this, 'enableWhiteLabelInterface'));
        add_action('wp_logout', array($this, 'disableWhiteLabelInterface'));
        add_action('admin_init', array($this, '_action_enqueue_editor_assets'), 9999);

        if (is_network_admin()) {
            add_action('network_admin_menu', array($this, 'actionRegisterPage'), 11);
        }

        if (get_transient(self::WL_SESSION_KEY) == 1) {
            add_action('admin_menu', array($this, 'actionRegisterPage'), 11);
        }

        // hide traces of brizy if the white labels was activated
        $values = $this->getValues();

        add_filter('brizy_wl_enabled', [$this, 'getEnabled']);

        if ($this->getEnabled()) {
            if (is_admin()) {
                add_filter('all_plugins', [$this, 'all_plugins']);
                add_filter('plugin_row_meta', [$this, 'plugin_row_meta'], 10, 2);
                add_filter('after_plugin_row_brizy-pro/brizy-pro.php', [$this, 'after_plugin_row'], 9, 2);
                add_filter('after_plugin_row_brizy/brizy.php', [$this, 'after_plugin_row'], 9, 2);
                add_action('core_upgrade_preamble', [$this, 'core_upgrade_preamble']);
                add_action('admin_head', [$this, 'admin_head']);
                add_action('admin_footer', [$this, 'admin_footer']);
                add_filter('gettext', function ($translated) use ($values) {

                    if ($translated == 'Brizy') {
                        return $values['brizy']->getValue();
                    }

                    return $translated;
                });
            }
        }

        add_filter('brizy_wl_value', array($this, 'filterKeys'), 11);
        add_filter('brizy_editor_config_texts', array($this, 'editorConfigTexts'));
        add_filter('brizy_upgrade_to_pro_url', [$this, 'upgradeToProUrl']);

        if (isset($_REQUEST['brz-action']) && $_REQUEST['brz-action'] == 'save-values') {
            add_action('admin_init', array($this, 'handleSubmit'));
        }

        if (isset($_REQUEST['brz-action']) && $_REQUEST['brz-action'] == 'reset-values') {
            add_action('admin_init', array($this, 'handleResetValues'), 10);
        }

        $this->values = $this->getValues();
    }

    public function _action_enqueue_editor_assets()
    {

        if (isset($_REQUEST['page']) && $_REQUEST['page'] === self::KEY) {
            // jQuery
            wp_enqueue_script('jquery');
            // This will enqueue the Media Uploader script
            wp_enqueue_media();
        }

    }

    public function enableWhiteLabelInterface()
    {
        if (!isset($_GET['brizy_enable_wl'])) {
            return;
        }

        if (!current_user_can('manage_options')) {
            return;
        }

        if (is_network_admin()) {
            $url = network_admin_url('admin.php?page=' . self::network_menu_slug(), false);
        } else {
            $url = menu_page_url(Brizy_Admin_Settings::menu_slug(), false);
        }

        set_transient(self::WL_SESSION_KEY, 1, 3 * HOUR_IN_SECONDS);

        header("location: " . $url);
        exit;
    }

    public function disableWhiteLabelInterface()
    {
        if (get_transient(self::WL_SESSION_KEY) == 1) {
            delete_transient(self::WL_SESSION_KEY);
        }
    }

    public function getDefaultValues()
    {
        return [
            'brizy' => new BrizyPro_Whitelabel_Value('brizy', 'text', 'Brizy', 'Company Name'),
            'description' => new BrizyPro_Whitelabel_Value(
                'description',
                'textarea',
                'A drag & drop front-end page builder to help you create WordPress pages lightning fast.',
                __('Description')
            ),
            'brizy-prefix' => new BrizyPro_Whitelabel_Value('brizy-refix', 'text', 'brizy', 'Prefix'),
            'brizy-logo' => new BrizyPro_Whitelabel_Value(
                'logo-brizy-text',
                'file',
                BRIZY_PLUGIN_URL . '/admin/static/img/brizy-logo.svg',
                'Logo (20px x 20px) .svg'
            ),
            'support-url' => new BrizyPro_Whitelabel_Value('support-url', 'text', Brizy_Config::SUPPORT_URL, 'Support URL'),
            'about-url' => new BrizyPro_Whitelabel_Value('about-url', 'text', Brizy_Config::ABOUT_URL, 'About URL'),
            'pro-url' => new BrizyPro_Whitelabel_Value('pro-url', 'text', Brizy_Config::UPGRADE_TO_PRO_URL, 'Upgrade to pro URL'),
            'starter-templates-url' => new BrizyPro_Whitelabel_Value('starter-templates-url', 'text', '', 'Starter templates URL'),
            'show-license-tab' => new BrizyPro_Whitelabel_Value('show-license-tab', 'checkbox', 0, 'Show license tab'),
        ];
    }

    /**
     * @return BrizyPro_Whitelabel_Value[]
     */
    public function getValues()
    {
        if ($this->values) {
            return $this->values;
        }

        $defaults = $this->getDefaultValues();

        if (is_multisite()) {
            if (is_network_admin()) {
                $data = get_network_option(null, self::KEY, $defaults);
            } else {
                $data = get_option(self::KEY);
                if (!$data) {
                    $data = get_network_option(null, self::KEY, $defaults);
                }
            }
        } else {
            $data = get_option(self::KEY, $defaults);
        }

        return $this->values = wp_parse_args($data, $defaults);
    }

    /**
     * @param $data
     *
     * @return $this
     * @throws Exception
     */
    public function saveValues($data)
    {
        $this->values = $data;

        if (is_network_admin()) {
            update_network_option(null, self::KEY, $data);
        } else {
            update_option(self::KEY, $data, true);
        }

        Brizy_Editor_Post::markAllForCompilation();

        return $this;
    }

    public function getEnabled()
    {
        if (!$this->values) {
            return false;
        }

        $values = $this->getValues();
        $enabled = false;

        if (isset($values['brizy']) && $values['brizy'] instanceof BrizyPro_Whitelabel_Value) {
            $enabled = $values['brizy']->getValue() != 'Brizy';
        }

        return $enabled;
    }

    public function showLicenseTab()
    {
        $values = $this->getValues();
        $show = false;

        if (isset($values['show-license-tab']) && $values['show-license-tab'] instanceof BrizyPro_Whitelabel_Value) {
            $show = $values['show-license-tab']->getValue();
        }


        return (bool)$show;
    }

    public function getPrefix()
    {

        $values = $this->getValues();
        $prefix = false;

        if (isset($values['brizy-prefix']) && $values['brizy-prefix'] instanceof BrizyPro_Whitelabel_Value) {
            $prefix = $values['brizy-prefix']->getValue();
        }

        return $prefix ? $prefix : 'brizy';
    }

    public function handleSubmit()
    {
        if (!current_user_can('manage_options')) {
            return;
        }

        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_wpnonce'])), 'validate-wl')) {
            if (is_network_admin()) {
                wp_redirect(network_admin_url('admin.php?page=' . self::network_menu_slug(), false));
                exit;
            } else {
                wp_redirect(menu_page_url(self::menu_slug(), false));
                exit;
            }
        }


        $data = array();

        if (isset($_POST['values']['brizy-prefix']['value'])) {
            $_POST['values']['brizy-prefix']['value'] = sanitize_title($_POST['values']['brizy-prefix']['value']);
        }

        foreach ($this->getDefaultValues() as $key => $defaultValue) {
            $value = isset($_POST['values'][$key]['value']) ? $_POST['values'][$key]['value'] : false;
            $data[$key] = new BrizyPro_Whitelabel_Value($key, $_POST['values'][$key]['type'], wp_unslash($value));
        }

        $this->saveValues($data);

        Brizy_Admin_Flash::instance()->add_success(__('Settings saved.', 'brizy-pro'));

        if (is_network_admin()) {
            wp_redirect(network_admin_url('admin.php?page=' . self::network_menu_slug(), false));
        } else {
            wp_redirect(menu_page_url(self::menu_slug(), false));
        }

        exit;
    }

    public function handleResetValues()
    {

        if (!current_user_can('manage_options')) {
            return;
        }

        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_wpnonce'])), 'validate-wl')) {
            if (is_network_admin()) {
                wp_redirect(network_admin_url('admin.php?page=' . self::network_menu_slug(), false));
                exit;
            } else {
                wp_redirect(menu_page_url(self::menu_slug(), false));
                exit;
            }
        }

        if (is_network_admin()) {
            $this->saveValues($this->getDefaultValues());
        } else {
            delete_option(self::KEY);
        }

        Brizy_Admin_Flash::instance()->add_success(__('Settings saved.', 'brizy-pro'));

        if (is_network_admin()) {
            wp_redirect(network_admin_url('admin.php?page=' . self::network_menu_slug(), false));
        } else {
            wp_redirect(menu_page_url(self::menu_slug(), false));
        }

        exit;
    }

    public function filterKeys($data)
    {

        if (isset($this->values[$data['key']]) && $this->values[$data['key']] instanceof BrizyPro_Whitelabel_Value) {
            return $this->values[$data['key']]->getValue();
        }

        return $data;
    }

    public function actionRegisterPage()
    {

        add_submenu_page(
            is_network_admin() ? Brizy_Admin_NetworkSettings::menu_slug() : Brizy_Admin_Settings::menu_slug(),
            __('White Label', 'brizy-pro'),
            __('White Label', 'brizy-pro'),
            is_network_admin() ? 'manage_network' : 'manage_options',
            is_network_admin() ? self::network_menu_slug() : self::menu_slug(),
            array($this, 'render')
        );
    }

    /**
     * @return void
     */
    public function render()
    {
        $labels = [
            'brizy' => __('Company Name', 'brizy-pro'),
            'description' => __('Description', 'brizy-pro'),
            'brizy-refix' => __('Prefix', 'brizy-pro'),
            'logo-brizy-text' => __('Logo (20px x 20px) .svg', 'brizy-pro'),
            'support-url' => __('Support URL', 'brizy-pro'),
            'about-url' => __('About URL', 'brizy-pro'),
            'pro-url' => __('Upgrade to pro URL', 'brizy-pro'),
            'starter-templates-url' => __('Starter templates URL', 'brizy-pro'),
            'show-license-tab' => __('Show license tab', 'brizy-pro'),
        ];

        $defaultValues = $this->getDefaultValues();

        foreach ($defaultValues as $defaultValue) {
            $key = $defaultValue->getKey();
            if (isset($labels[$key])) {
                $defaultValue->setLabel($labels[$key]);
            }
        }

        $context = array(
            'action' => add_query_arg('brz-action', 'save-values', menu_page_url(self::menu_slug(), false)),
            'resetAction' => wp_nonce_url(add_query_arg('brz-action', 'reset-values', menu_page_url(self::menu_slug(), false)), 'validate-wl'),
            'nonce' => wp_nonce_field('validate-wl', '_wpnonce', true, false),
            'defaultData' => $defaultValues,
            'data' => $this->getValues(),
            'submit_label' => 'Save Changes',
            'message' => isset($_REQUEST['message']) ? htmlentities($_REQUEST['message']) : null,
        );

        Brizy_Editor_View::render(BRIZY_PRO_PLUGIN_PATH . '/admin/views/white-label', $context);
    }

    public static function menu_slug()
    {
        return self::KEY;
    }

    public static function network_menu_slug()
    {
        return 'network-' . self::KEY;
    }

    public function editorConfigTexts($texts)
    {

        if (!$this->getEnabled()) {
            return $texts;
        }

        $brizy = __bt('brizy', 'Brizy');

        foreach ($texts as $key => $text) {
            if (strpos($text, 'Brizy') !== false) {
                $texts[$key] = str_replace('Brizy', $brizy, $text);
            }
        }

        return $texts;
    }

    public function all_plugins($plugins)
    {

        $values = $this->getValues();

        $data = [
            'Name' => $values['brizy']->getValue(),
            'PluginURI' => $values['about-url']->getValue(),
            'Description' => $values['description']->getValue(),
            'Author' => $values['brizy']->getValue(),
            'AuthorURI' => $values['about-url']->getValue(),
            'Title' => $values['brizy']->getValue(),
        ];

        if (array_key_exists('brizy/brizy.php', $plugins)) {
            $plugins['brizy/brizy.php'] = wp_parse_args($data, $plugins['brizy/brizy.php']);
        }

        if (array_key_exists('brizy-pro/brizy-pro.php', $plugins)) {
            $data['Name'] = $data['Name'] . ' Pro';
            $plugins['brizy-pro/brizy-pro.php'] = wp_parse_args($data, $plugins['brizy-pro/brizy-pro.php']);
        }

        return $plugins;
    }

    public function plugin_row_meta($plugin_meta, $plugin_file)
    {

        if (!in_array($plugin_file, ['brizy/brizy.php', 'brizy-pro/brizy-pro.php'])) {
            return $plugin_meta;
        }

        $plugin_meta = array_filter($plugin_meta, function ($value) {
            return (strpos($value, 'plugin-information') === false);
        });

        return $plugin_meta;
    }

    /**
     * Rewrite the function(wp_plugin_update_row), hook added by function wp_plugin_update_rows on each plugin row in the admin plugins list.
     *
     * @param $file
     * @param $plugin_data
     *
     * @return void|false
     */
    public function after_plugin_row($file, $plugin_data)
    {

        remove_filter('after_plugin_row_brizy/brizy.php', 'wp_plugin_update_row');
        remove_filter('after_plugin_row_brizy-pro/brizy-pro.php', 'wp_plugin_update_row');

        $current = get_site_transient('update_plugins');
        if (!isset($current->response[$file])) {
            return false;
        }

        $response = $current->response[$file];

        $plugins_allowedtags = array(
            'a' => array(
                'href' => array(),
                'title' => array(),
            ),
            'abbr' => array('title' => array()),
            'acronym' => array('title' => array()),
            'code' => array(),
            'em' => array(),
            'strong' => array(),
        );

        $plugin_name = wp_kses($plugin_data['Name'], $plugins_allowedtags);
        $details_url = self_admin_url(
            'plugin-install.php?tab=plugin-information&plugin=' . $response->slug . '&section=changelog&TB_iframe=true&width=600&height=800'
        );

        /** @var WP_Plugins_List_Table $wp_list_table */
        $wp_list_table = _get_list_table(
            'WP_Plugins_List_Table',
            array(
                'screen' => get_current_screen(),
            )
        );

        if (is_network_admin() || !is_multisite()) {
            if (is_network_admin()) {
                $active_class = is_plugin_active_for_network($file) ? ' active' : '';
            } else {
                $active_class = is_plugin_active($file) ? ' active' : '';
            }

            $requires_php = isset($response->requires_php) ? $response->requires_php : null;
            $compatible_php = is_php_version_compatible($requires_php);
            $notice_type = $compatible_php ? 'notice-warning' : 'notice-error';

            printf(
                '<tr class="plugin-update-tr%s" id="%s" data-slug="%s" data-plugin="%s">' .
                '<td colspan="%s" class="plugin-update colspanchange">' .
                '<div class="update-message notice inline %s notice-alt"><p>',
                $active_class,
                esc_attr($response->slug . '-update'),
                esc_attr($response->slug),
                esc_attr($file),
                esc_attr($wp_list_table->get_column_count()),
                $notice_type
            );

            if (!current_user_can('update_plugins')) {
                printf(
                /* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number. */
                    __('There is a new version(%1$s) of %2$s available.', 'brizy-pro'),
                    $response->new_version,
                    $plugin_name
                );
            } elseif (empty($response->package)) {
                printf(
                /* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number. */
                    __(
                        'There is a new version(%1$s) of %2$s available. <em>Automatic update is unavailable for this plugin.</em>',
                        'brizy-pro'
                    ),
                    $response->new_version,
                    $plugin_name
                );
            } else {
                if ($compatible_php) {
                    printf(
                    /* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number, 5: Update URL, 6: Additional link attributes. */
                        __('There is a new version(%1$s) of %2$s available. Please <a href="%3$s" %4$s>update now</a>.', 'brizy-pro'),
                        $response->new_version,
                        $plugin_name,
                        wp_nonce_url(self_admin_url('update.php?action=upgrade-plugin&plugin=') . $file, 'upgrade-plugin_' . $file),
                        sprintf(
                            'class="update-link" aria-label="%s"',
                            /* translators: %s: Plugin name. */
                            esc_attr(sprintf(_x('Update %s now', 'plugin'), $plugin_name))
                        )
                    );
                } else {
                    printf(
                    /* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number 5: URL to Update PHP page. */
                        __(
                            'There is a new version(%1$s) of %2$s available, but it doesn&#8217;t work with your version of PHP. <a href="%3$s">Learn more about updating PHP</a>.',
                            'brizy-pro'
                        ),
                        $response->new_version,
                        $plugin_name,
                        esc_url(wp_get_update_php_url())
                    );
                    wp_update_php_annotation('<br><em>', '</em>');
                }
            }

            /**
             * Fires at the end of the update message container in each
             * row of the plugins list table.
             *
             * The dynamic portion of the hook name, `$file`, refers to the path
             * of the plugin's primary file relative to the plugins directory.
             *
             * @param array $plugin_data {
             *     An array of plugin metadata.
             *
             * @type string $name The human-readable name of the plugin.
             * @type string $plugin_uri Plugin URI.
             * @type string $version Plugin version.
             * @type string $description Plugin description.
             * @type string $author Plugin author.
             * @type string $author_uri Plugin author URI.
             * @type string $text_domain Plugin text domain.
             * @type string $domain_path Relative path to the plugin's .mo file(s).
             * @type bool $network Whether the plugin can only be activated network wide.
             * @type string $title The human-readable title of the plugin.
             * @type string $author_name Plugin author's name.
             * @type bool $update Whether there's an available update. Default null.
             * }
             * @param array $response {
             *     An array of metadata about the available plugin update.
             *
             * @type int $id Plugin ID.
             * @type string $slug Plugin slug.
             * @type string $new_version New plugin version.
             * @type string $url Plugin URL.
             * @type string $package Plugin update package URL.
             * }
             * @since 2.8.0
             *
             */
            do_action(
                "in_plugin_update_message-{$file}",
                $plugin_data,
                $response
            ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

            echo '</p></div></td></tr>';
        }
    }

    public function core_upgrade_preamble()
    {

        echo
        "<script>
				( function( $ ) {
	                $( 'input[value=\"brizy/brizy.php\"]' ).closest( 'tr' ).find( '.open-plugin-details-modal' ).remove();
	                $( 'input[value=\"brizy-pro/brizy-pro.php\"]' ).closest( 'tr' ).find( '.open-plugin-details-modal' ).remove();
				} )( jQuery );
			</script>";
    }

    public function admin_head()
    {

        $current_screen = get_current_screen();

        add_action('gettext_brizy', [$this, 'gettext_domain'], 10, 2);
        add_action('gettext_brizy-pro', [$this, 'gettext_domain'], 10, 2);

        if ($current_screen->id == 'update-core') {
            ob_start([$this, 'replaceWlUpdateCore']);
        }
    }

    public function add_custom_css()
    {


    }

    public function replaceWlUpdateCore($buffer)
    {

        $values = $this->getValues();

        $html = preg_replace('/https:\/\/ps.w.org\/brizy\/assets\/[^"]*/', $values['brizy-logo']->getValue(), $buffer);

        return $html ? $html : $buffer;
    }

    public function admin_footer()
    {

        $current_screen = get_current_screen();

        if ($current_screen->id == 'update-core') {
            ob_end_flush();
        }
    }

    public function gettext_domain($translation, $text)
    {
        $values = $this->getValues();

        if ($text == 'Brizy') {
            $translation = $values['brizy']->getValue();
        }

        if ($text == 'Brizy Pro') {
            $translation = $values['brizy']->getValue() . ' Pro';
        }

        if ($text == 'Brizy.io') {
            $translation = $values['brizy']->getValue();
        }

        if ($text == 'https://brizy.io/') {
            $translation = $values['about-url']->getValue();
        }

        if ($text == 'Extended functionality for the Brizy WordPress builder plugin.') {
            $translation = $values['description']->getValue();
        }

        if ($text == "A free drag & drop front-end page builder to help you create WordPress pages lightning fast. It's easy with Brizy.") {
            $translation = $values['description']->getValue();
        }

        return $translation;
    }

    /**
     * $input = [
     *      'license'          => 'a-valid-license',
     *      'brizy'            => 'My Plugin Name',
     *      'description'      => 'A drag & drop front-end page builder to help you create WordPress pages lightning fast.',
     *      'brizy-prefix'     => 'prefix',
     *      'support-url'      => 'https://support.brizy.io',
     *      'about-url'        => 'https://brizy.io',
     *      'brizy-logo'       => 'https://brizy.com/admin/static/img/brizy-logo.svg',
     *      'pro-url'          => 'https://www.brizy.io/pricing/',
     *      'show-license-tab' => false
     *  ]
     * @param $input
     *
     * @return bool
     * @throws Exception
     */
    public function installWhiteLabel($input)
    {
        if (!empty($input['license'])) {
            BrizyPro_Admin_License::_init()->activate(['key' => $input['license']]);
        }

        $wlData = $this->getDefaultValues();

        foreach ($wlData as $key => $wlValue) {
            if (!isset($input[$key])) {
                continue;
            }

            $wlValue->setValue($input[$key]);
        }

        $this->saveValues($wlData);

        return true;
    }

    public function upgradeToProUrl($url)
    {
        return $this->getEnabled() && !empty($this->getValues()['pro-url']) ? $this->getValues()['pro-url']->getValue() : $url;
    }
}
