<?php

namespace DiviBooster\DiviBooster\Licensing;

$licensing = new Licensing(
    $config['plugin_file'],
    $config['plugin_slug'],
    $config['plugin_name'],
    $config['plugin_url'],
    $config['edd_store_url'],
    $config['edd_item_id']
);
$licensing->init();

class Licensing {

    private $plugin_name;
    private $settings_page;
    private $license_key_option;
    private $license_status_option;
    private $settings_fields;
    private $plugin_file;
    private $settings_nonce;
    private $plugin_url;
    private $store_url; // URL of site with EDD store
    private $store_item_id; // id of the plugin in EDD
    private $plugin_slug;

    public function __construct($plugin_file, $plugin_slug, $plugin_name, $plugin_url, $store_url, $store_item_id) {
        $this->plugin_file = $plugin_file;
        $this->plugin_slug = $plugin_slug;
        $this->plugin_name = $plugin_name;
        $this->plugin_url = $plugin_url;
        $this->store_url = $store_url;
        $this->store_item_id = $store_item_id;

        $this->settings_page = $this->plugin_slug . '-settings';
        $this->settings_fields = $this->plugin_slug . '-license';
        $this->license_key_option = $this->plugin_slug . '-license_key';
        $this->license_status_option = $this->plugin_slug . '-license_status';
        $this->settings_nonce = $this->plugin_slug . '-nonce';
    }

    public function init() {
        add_action('admin_menu', array($this, 'dbal_license_menu'));
        add_filter("db-settings-{$this->plugin_slug}-tabs", array($this, 'register_settings_tab'), 11);
        add_action("db-{$this->plugin_slug}-updated", array($this, 'dbal_check_license'));
        add_action('admin_init', array($this, 'dbal_register_option'));
        add_action('admin_init', array($this, 'dbal_deactivate_license'));
        add_action('admin_init', array($this, 'dbal_activate_license'), 11);
        add_action('admin_notices', array($this, 'dbal_admin_notices'), 0); // Register early
        add_action('admin_notices', array($this, 'hide_unrelated_admin_notices'), 1); // Hide all registered later
        add_action('after_plugin_row_' . plugin_basename($this->plugin_file), array($this, 'dbal_after_plugin_row'), 20, 3);
        add_action('admin_head', array($this, 'dbal_plugins_php_license_required_css'));
    }

    function dbal_check_license() {
        $license = trim(get_option($this->license_key_option));
        if (empty($license)) {
            delete_option($this->license_status_option);
        } else {
            $response = $this->dbal_submit_license('check', $license);
            if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
                return;
            }
            $license_data = json_decode(wp_remote_retrieve_body($response));
            if (isset($license_data->license) && $license_data->license === 'invalid') {
                delete_option($this->license_status_option);
            }
        }
    }

    function hide_unrelated_admin_notices() {
        if (isset($_GET['page']) && $_GET['page'] === $this->settings_page) {
            remove_all_actions('admin_notices');
        }
    }

    function dbal_license_menu() {
        add_options_page($this->plugin_name, $this->plugin_name, 'manage_options', $this->settings_page, array($this, 'dbal_license_page'));
    }

    function register_settings_tab($tabs) {
        if (!is_array($tabs)) {
            return $tabs;
        }
        $tabs['updates'] = array(
            'title' => 'Updates',
            'url' => admin_url("/options-general.php?page={$this->plugin_slug}-settings"),
        );
        return $tabs;
    }


    function dbal_license_page() {
        add_filter("db-settings-{$this->plugin_slug}-active-tab", function () {
            return 'updates';
        });
        $license = get_option($this->license_key_option);
        $status  = get_option($this->license_status_option, false);
?>
        <div class="db-settings-wrap">
            <form method="post" action="options.php">

                <?php settings_fields($this->settings_fields); ?>
                <?php wp_nonce_field($this->settings_nonce, $this->settings_nonce); ?>

                <?php do_action('db-settings-settings-box-before'); ?>
                <div id="db-settings-box">
                    <h1 id="db-settings-box-title"><?php esc_html_e($this->plugin_name); ?> Settings</h1>
                    <?php do_action('db-settings-title-after', $this->plugin_slug); ?>
                    <div class="db-settings-box-tab-content">
                        <table class="db-settings-box-tab-content-table form-table">
                            <tbody>
                                <tr valign="top">
                                    <th scope="row" valign="top">
                                        <?php _e('License Key'); ?>
                                    </th>
                                    <td>
                                        <input id="<?php esc_attr_e($this->license_key_option); ?>" name="<?php esc_attr_e($this->license_key_option); ?>" type="password" class="regular-text" value="<?php esc_attr_e($license); ?>" />
                                        <?php if ($status !== false && $status == 'valid') { ?>
                                            <input type="submit" class="button-secondary" name="edd_license_deactivate" value="<?php _e('Deactivate'); ?>" />
                                            <span style="color:green;line-height:28px;margin-right:1em;margin-left: 1em;"><?php _e('Active'); ?></span>
                                        <?php } else { ?>
                                            <span style="color:red;line-height:28px;margin-right:1em;margin-left: 1em;"><?php _e('Inactive'); ?></span>
                                            <p>Enter your license key to enable updates.</p>
                                            <p>You can get your license key from your <a href="https://divibooster.com/your-account/" target="_blank">Divi Booster account</a>, or <a href="<?php esc_attr_e($this->plugin_url); ?>" target="_blank">purchase a license</a>.</p>
                                        <?php } ?>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
                <?php submit_button(); ?>

            </form>
            <?php
        }

        // === Register the license key option ===

        function dbal_register_option() {
            // creates our settings in the options table
            register_setting($this->settings_fields, $this->license_key_option, array($this, 'dbal_sanitize_license'));
        }

        function dbal_sanitize_license($new) {
            $old = get_option($this->license_key_option);
            if ($old && $old != $new) {
                delete_option($this->license_status_option); // new license has been entered, so must reactivate
            }
            return $new;
        }


        // === License activation ===


        function dbal_activate_license() {

            if (isset($_POST['option_page']) && $_POST['option_page'] === $this->settings_fields) {
                // run a quick security check
                if (!check_admin_referer($this->settings_nonce, $this->settings_nonce))
                    return; // get out if we didn't click the Activate button

                // Get the license
                $license = trim($_POST[$this->license_key_option]);
                $license = strtolower($license);

                update_option($this->license_key_option, $license);

                $response = $this->dbal_submit_license('activate', $license);
                $message = $this->activation_error($response);

                // Check if anything passed on a message constituting a failure
                if (!empty($message)) {
                    $base_url = admin_url('options-general.php?page=' . $this->settings_page);
                    $redirect = add_query_arg(array('sl_activation' => 'false', 'plugin' => $this->plugin_slug, 'message' => urlencode($message)), $base_url);
                    wp_redirect($redirect);
                    exit();
                }
                // $license_data->license will be either "valid" or "invalid"
                $license_data = json_decode(wp_remote_retrieve_body($response));
                $validity = $license_data->license;

                // If license server not responding correctly, allow license to validate locally instead of throwing an error
                if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) !== 200) {
                    $validity = 'valid';
                }

                update_option($this->license_status_option, $validity);

                wp_redirect(admin_url('options-general.php?page=' . $this->settings_page));
                exit();
            }
        }

        // Return the activation error, if any, from the given response / WP_Error object
        public function activation_error($response) {
            $message = '';
            if (is_wp_error($response)) {
                $message =  ($response->get_error_message() !== '') ? $response->get_error_message() : __('An error occurred while connecting to the license server, please try again.');
                $message .= ($response->get_error_code() !== '') ? ' (Error code ' . $response->get_error_code() . ')' : '';
            } elseif (wp_remote_retrieve_response_code($response) !== 200) {
                $message = ''; // If license server not responding correctly, allow license to validate locally instead of throwing an error
                //$message = sprintf('An error (HTTP code %d) occurred while connecting to the license server, please try again.', wp_remote_retrieve_response_code($response));
            } else {
                $license_data = json_decode(wp_remote_retrieve_body($response));
                if (false === $license_data->success) {
                    switch ($license_data->error) {
                        case 'expired':
                            $message = sprintf(
                                __('Your license key expired on %s.'),
                                date_i18n(get_option('date_format'), strtotime($license_data->expires, current_time('timestamp')))
                            );
                            break;
                        case 'revoked':
                            $message = __('Your license key has been disabled.');
                            break;
                        case 'missing':
                            $message = __('Invalid license.');
                            break;
                        case 'invalid_item_id':
                            $message = sprintf(__('Sorry, that license key is for a different plugin by Divi Booster. Please use a license key for the %s plugin.'), $this->plugin_name);
                            break;
                        case 'invalid':
                        case 'site_inactive':
                            $message = __('Your license is not active for this URL.');
                            break;
                        case 'item_name_mismatch':
                            $message = sprintf(__('This appears to be an invalid license key for %s.'), $this->plugin_name);
                            break;
                        case 'no_activations_left':
                            $message = __('Your license key has reached its activation limit.');
                            break;
                        default:
                            $message = __('An error occurred, please try again. (error code: ' . esc_html($license_data->error) . ')');
                            break;
                    }
                }
            }
            return $message;
        }


        // === License deactivation ===


        function dbal_deactivate_license() {
            if (isset($_POST['option_page']) && $_POST['option_page'] !== $this->settings_fields) {
                return;
            }

            // listen for our activate button to be clicked
            if (isset($_POST['edd_license_deactivate'])) {


                // run a quick security check
                if (!check_admin_referer($this->settings_nonce, $this->settings_nonce))
                    return; // get out if we didn't click the Activate button

                // retrieve the license from the database
                $license = trim(get_option($this->license_key_option));

                if (!$this->dbal_license_deactivated_in_edd($license)) {
                    $this->dbal_submit_license('deactivate', $license);
                }

                update_option($this->license_status_option, 'deactivated');
                wp_redirect(admin_url('options-general.php?page=' . $this->settings_page));
                exit();
            }
        }

        function dbal_license_deactivated_in_edd($license) {
            $deactivated = false;
            $response = $this->dbal_submit_license('check', $license);
            if (!is_wp_error($response)) {
                $license_data = json_decode(wp_remote_retrieve_body($response));
                if ($license_data->license === 'inactive') {
                    $deactivated = true;
                }
            }
            return $deactivated;
        }

        function dbal_submit_license($action, $license) {
            $result = wp_remote_post(
                $this->store_url,
                array(
                    'timeout' => 30,
                    'body' => array(
                        'edd_action' => $action . '_license',
                        'license'    => $license,
                        'item_id'    => $this->store_item_id,
                        'url'        => home_url()
                    )
                )
            );
            return $result;
        }

        // === Display license activation / deactivation errors to user ===


        function dbal_admin_notices() {
            if (empty($_GET['page']) || $_GET['page'] !== $this->settings_page) {
                return;
            }
            if (empty($_GET['plugin']) || $_GET['plugin'] !== $this->plugin_slug) {
                return;
            }
            if (isset($_GET['sl_activation']) && !empty($_GET['message'])) {
                switch ($_GET['sl_activation']) {
                    case 'false':
                        $message = urldecode($_GET['message']);
            ?>
                        <div class="error">
                            <p><?php esc_html_e($message); ?></p>
                        </div>
                    <?php
                        break;
                    case 'true':
                    default:
                        // Can put a custom success message here for when activation is successful if they want.
                        break;
                }
            }
            if (isset($_GET['sl_deactivation']) && !empty($_GET['message'])) {
                switch ($_GET['sl_deactivation']) {
                    case 'false':
                        $message = urldecode($_GET['message']);
                    ?>
                        <div class="error">
                            <p>Error: <?php esc_html_e($message); ?></p>
                        </div>
            <?php
                        break;
                    case 'true':
                    default:
                        // Can put a custom success message here for when activation is successful if they want.
                        break;
                }
            }
        }

        // === Notify admin via plugins.php that license required to activate plugin ===


        function dbal_after_plugin_row($plugin_file, $plugin_data, $status) {

            // Don't display message if the plugin is correctly licensed
            if (get_option($this->license_status_option) === 'valid') {
                return;
            }

            // Display license message
            $settings_url = admin_url('options-general.php?page=' . $this->settings_page);
            ?>
            <tr class="plugin-update-tr active">
                <td colspan="4" class="plugin-update colspanchange">
                    <div class="update-message notice inline notice-warning notice-alt">
                        <p>Enter your license key on the <a href="<?php esc_attr_e($settings_url); ?>">settings page</a> to enable updates. You can get your license from your <a href="https://divibooster.com/your-account/purchase-history/" target="_blank">Divi Booster account</a>, or <a href="<?php esc_attr_e($this->plugin_url); ?>" target="_blank">purchase a license</a>.</p>
                    </div>
                </td>
            </tr>
        <?php
        }


        function dbal_plugins_php_license_required_css() {

            // Make sure we're on plugins.php
            global $pagenow;
            if ($pagenow !== 'plugins.php') {
                return;
            }

            // Don't add CSS if the plugin is correctly licensed
            if (get_option($this->license_status_option) === 'valid') {
                return;
            }

            // Remove border bottom after shortcode enabler plugin entry
        ?>
            <style>
                .plugins tr[data-slug="<?php esc_attr_e($this->plugin_slug); ?>"].active td,
                .plugins tr[data-slug="<?php esc_attr_e($this->plugin_slug); ?>"].active th {
                    box-shadow: none !important;
                }
            </style>
    <?php
        }
    }
