<?php
/**
 * This file belongs to the YIT Plugin Framework.
 *
 * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.gnu.org/licenses/gpl-3.0.txt
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
} // Exit if accessed directly

if ( ! class_exists( 'YIT_Licence' ) ) {
    /**
     * YIT Licence Panel
     *
     * Setting Page to Manage Products
     *
     * @class      YIT_Licence
     * @package    Yithemes
     * @since      1.0
     * @author     Andrea Grillo      <andrea.grillo@yithemes.com>
     */

    abstract class YIT_Licence {

        /**
         * @var mixed array The registered products info
         * @since 1.0
         */
        protected $_products = array();

        /**
         * @var array The settings require to add the submenu page "Activation"
         * @since 1.0
         */
        protected $_settings = array();

        /**
         * @var string Option name
         * @since 1.0
         */
        protected $_licence_option = 'yit_products_licence_activation';

         /**
         * @var string The yithemes api uri
         * @since 1.0
         */
        protected $_api_uri = 'https://yithemes.com';

        /**
         * @var string The yithemes api uri query args
         * @since 1.0
         */
        protected $_api_uri_query_args = '?wc-api=software-api&request=%request%';


        /**
         * @var string check for show extra info
         * @since 1.0
         */
        public $show_extra_info = false;

         /**
         * @var string check for show extra info
         * @since 1.0
         */
        public $show_renew_button = true;

        /**
         * Constructor
         *
         * @since    1.0
         * @author   Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function __construct() {
            $is_debug_enabled = defined( 'YIT_LICENCE_DEBUG' ) && YIT_LICENCE_DEBUG;
            if ( $is_debug_enabled ) {
                $this->_api_uri = defined( 'YIT_LICENCE_DEBUG_LOCALHOST' ) ? YIT_LICENCE_DEBUG_LOCALHOST : 'http://dev.yithemes.com';
                add_filter( 'block_local_requests', '__return_false' );
            }

            /* Style adn Script */
            add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
            if( $is_debug_enabled ) {
                //show extra info and renew button in debug mode
                $this->show_extra_info = $this->show_renew_button = true;
            }

            else {
                $this->show_extra_info   = defined( 'YIT_SHOW_EXTRA_LICENCE_INFO' )    && YIT_SHOW_EXTRA_LICENCE_INFO;
                $this->show_renew_button = ! ( defined( 'YIT_HIDE_LICENCE_RENEW_BUTTON' )  && YIT_HIDE_LICENCE_RENEW_BUTTON );
            }

            /* Update Licence Information */
            //@TODO: Removed for performance
//            add_action( 'core_upgrade_preamble', array( $this, 'check_all' ) );
//            add_action( 'wp_maybe_auto_update',  array( $this, 'check_all' ) );

        }

        /**
         * Premium products registration
         *
         * @param $init         string | The products identifier
         * @param $secret_key   string | The secret key
         * @param $product_id   string | The product id
         *
         * @return void
         *
         * @since    1.0
         * @author   Andrea Grillo <andrea.grillo@yithemes.com>
         */
        abstract public function register( $init, $secret_key, $product_id );

        /**
         * Get protected array products
         *
         * @return mixed array
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_products() {
            return $this->_products;
        }

        /**
         * Get The home url without protocol
         *
         * @return string | The home url
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_home_url() {
            $home_url   = home_url();
            $schemes    = apply_filters( 'yit_licence_url_schemes', array( 'https://', 'http://' ) );

            foreach( $schemes as $scheme ){
                $home_url = str_replace( $scheme, '', $home_url );
            }

            return apply_filters('yit_licence_get_home_url', $home_url );
        }

        /**
         * Check if the request is ajax
         *
         * @return bool true if the request is ajax, false otherwise
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function is_ajax() {
            return defined( 'DOING_AJAX' ) && DOING_AJAX ? true : false;
        }

         /**
         * Admin Enqueue Scripts
         *
         * @return void
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function admin_enqueue_scripts(){

            /**
             * Support to YIT Framework < 2.0
             */
            $filename       = function_exists( 'yit_load_js_file' ) ? yit_load_js_file( 'yit-licence.js' ) : 'yit-licence.js';
            $script_path    = defined( 'YIT_CORE_PLUGIN_URL' ) ? YIT_CORE_PLUGIN_URL : get_template_directory_uri() . '/core/plugin-fw';
            $style_path     = defined( 'YIT_CORE_PLUGIN_URL' ) ? YIT_CORE_PLUGIN_URL : get_template_directory_uri() . '/core/plugin-fw';

            wp_enqueue_script( 'yit-licence', $script_path . '/licence/assets/js/' . $filename, array( 'jquery' ), '1.0.0', true );
            wp_enqueue_style( 'yit-theme-licence', $style_path . '/licence/assets/css/yit-licence.css' );

            /* Localize Scripts */
            wp_localize_script( 'yit-licence', 'licence_message', array(
                    'error'         => sprintf( _x( '%s field cannot be empty', '%s = field name', 'yith-plugin-fw' ), '%field%' ),  // sprintf must be used to avoid errors with '%field%' string in translation in .po file
                    'errors'        => sprintf( __( '%s and %s fields cannot be empty', 'yith-plugin-fw' ), '%field_1%', '%field_2%' ),
                    'server'        => __( 'Unable to contact the remote server, please try again later. Thanks!', 'yith-plugin-fw' ),
                    'email'         => __( 'Email', 'yith-plugin-fw' ),
                    'license_key'   => __( 'License Key', 'yith-plugin-fw' ),
                    'are_you_sure'  => __( 'Are you sure you want to deactivate the license for current site?', 'yith-plugin-fw' )
                )
            );

            wp_localize_script( 'yit-licence', 'script_info', array(
                    'is_debug' => defined( 'YIT_LICENCE_DEBUG' ) && YIT_LICENCE_DEBUG
                )
            );
        }

        /**
         * Activate Plugins
         *
         * Send a request to API server to activate plugins
         *
         * @return void
         * @use wp_send_json
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function activate() {
            $product_init = $_REQUEST['product_init'];
            $product      = $this->get_product( $product_init );

            $args = array(
                'email'       => urlencode( sanitize_email( $_REQUEST['email'] ) ),
                'licence_key' => sanitize_text_field( $_REQUEST['licence_key'] ),
                'product_id'  => sanitize_text_field( $product['product_id'] ),
                'secret_key'  => sanitize_text_field( $product['secret_key'] ),
                'instance'    => $this->get_home_url()
            );

            $api_uri  = esc_url_raw( add_query_arg( $args, $this->get_api_uri( 'activation' ) ) );
            $response = wp_remote_get( $api_uri, array( 'timeout' => 30 ) );

            if ( is_wp_error( $response ) ) {
                $body = false;
            }
            else {
                $body = json_decode( $response['body'] );
                $body = is_object( $body ) ? get_object_vars( $body ) : false;
            }

            if ( $body && is_array( $body ) && isset( $body['activated'] ) && $body['activated'] ) {

                $option[$product['product_id']] = array(
                    'email'                 => urldecode( $args['email'] ),
                    'licence_key'           => $args['licence_key'],
                    'licence_expires'       => $body['licence_expires'],
                    'message'               => $body['message'],
                    'activated'             => true,
                    'activation_limit'      => $body['activation_limit'],
                    'activation_remaining'  => $body['activation_remaining'],
                    'is_membership'         => isset( $body['is_membership'] ) ? $body['is_membership'] : false,
                );

                /* === Check for other plugins activation === */
                $options                        = $this->get_licence();
                $options[$product['product_id']] = $option[$product['product_id']];

                update_option( $this->_licence_option, $options );

                /* === Update Plugin Licence Information === */
                YIT_Upgrade()->force_regenerate_update_transient();

                /* === Licence Activation Template === */
                $body['template'] = $this->show_activation_panel( $this->get_response_code_message( 200 ) );
            }

            wp_send_json( $body );
        }

        /**
         * Deactivate Plugins
         *
         * Send a request to API server to activate plugins
         *
         * @return void
         * @use wp_send_json
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function deactivate() {
            $product_init = $_REQUEST['product_init'];
            $product      = $this->get_product( $product_init );

            $args = array(
                'email'       => urlencode( sanitize_email( $_REQUEST['email'] ) ),
                'licence_key' => sanitize_text_field( $_REQUEST['licence_key'] ),
                'product_id'  => sanitize_text_field( $product['product_id'] ),
                'secret_key'  => sanitize_text_field( $product['secret_key'] ),
                'instance'    => $this->get_home_url()
            );

            $api_uri  = esc_url_raw( add_query_arg( $args, $this->get_api_uri( 'deactivation' ) ) );
            $response = wp_remote_get( $api_uri, array( 'timeout' => 30 ) );

            if ( is_wp_error( $response ) ) {
                $body = false;
            }
            else {
                $body = json_decode( $response['body'] );
                $body = is_object( $body ) ? get_object_vars( $body ) : false;
            }

            if ( $body && is_array( $body ) && isset( $body['activated'] ) && ! $body['activated'] && ! isset( $body['error'] ) ) {

                 $option[$product['product_id']] = array(
                     'activated'            => false,
                     'email'                => urldecode( $args['email'] ),
                     'licence_key'          => $args['licence_key'],
                     'licence_expires'      => $body['licence_expires'],
                     'message'              => $body['message'],
                     'activation_limit'     => $body['activation_limit'],
                     'activation_remaining' => $body['activation_remaining'],
                     'is_membership'        => isset( $body['is_membership'] ) ? $body['is_membership'] : false,
                );

                /* === Check for other plugins activation === */
                $options                         = $this->get_licence();
                $options[$product['product_id']] = $option[$product['product_id']];

                update_option( $this->_licence_option, $options );

                /* === Update Plugin Licence Information === */
                YIT_Upgrade()->force_regenerate_update_transient();

                /* === Licence Activation Template === */
                $body['template'] = $this->show_activation_panel( $this->get_response_code_message( 'deactivated', array( 'instance' => $body['instance'] ) ) );
            }

            else {
                $body['error'] = $this->get_response_code_message( $body['code'] );
            }

            wp_send_json( $body );
        }

        /**
         * Check Plugins Licence
         *
         * Send a request to API server to check if plugins is activated
         *
         * @param string|The plugin init slug $plugin_init
         *
         * @return bool | true if activated, false otherwise
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function check( $product_init, $regenerate_transient = true ) {

            $status     = false;
            $body       = false;
            $product    = $this->get_product( $product_init );
            $licence    = $this->get_licence();
            $product_id = $product['product_id'];

            if( ! isset( $licence[ $product_id ] ) ) {
                return false;
            }

            $args = array(
                'email'       => urlencode( $licence[$product_id]['email'] ),
                'licence_key' => $licence[$product_id]['licence_key'],
                'product_id'  => $product_id,
                'secret_key'  => $product['secret_key'],
                'instance'    => $this->get_home_url()
            );

            $api_uri  = esc_url_raw( add_query_arg( $args, $this->get_api_uri( 'check' ) ) );
            $response = wp_remote_get( $api_uri, array( 'timeout' => 30 ) );

            if ( ! is_wp_error( $response ) ) {
                $body = json_decode( $response['body'] );
                $body = is_object( $body ) ? get_object_vars( $body ) : false;
            }

            if ( $body && is_array( $body ) && isset( $body['success'] ) ) {
                if ( $body['success'] ) {

                    /**
                     * Code 200 -> Licence key is valid
                     */
                    $licence[ $product_id ]['status_code']          = '200';
                    $licence[ $product_id ]['activated']            = $body['activated'];
                    $licence[ $product_id ]['licence_expires']      = $body['licence_expires'];
                    $licence[ $product_id ]['activation_remaining'] = $body['activation_remaining'];
                    $licence[ $product_id ]['activation_limit']     = $body['activation_limit'];
                    $licence[ $product_id ]['is_membership']        = isset( $body['is_membership'] ) ? $body['is_membership'] : false;
                    $status                                         = (bool) $body['activated'];
                }
                elseif ( isset( $body['code'] ) ) {

                    switch ( $body['code'] ) {

                        /**
                         * Error Code List:
                         *
                         * 100 -> Invalid Request
                         * 101 -> Invalid licence key
                         * 102 -> Software has been deactivate
                         * 103 -> Exceeded maximum number of activations
                         * 104 -> Invalid instance ID
                         * 105 -> Invalid security key
                         * 106 -> Licence key has expired
                         * 107 -> Licence key has be banned
                         *
                         * Only code 101, 106 and 107 have effect on DB during activation
                         * All error code have effect on DB during deactivation
                         *
                         */

                        case '101':
                        case '102':
                            unset( $licence[ $product_id ] );
                            break;

                        case '106':
                            $licence[ $product_id ]['activated']        = false;
                            $licence[ $product_id ]['message']          = $body['error'];
                            $licence[ $product_id ]['status_code']      = $body['code'];
                            $licence[ $product_id ]['licence_expires']  = $body['licence_expires'];
                            //$licence[ $product_id ]['is_membership']    = isset( $body['is_membership'] ) ? $body['is_membership'] : false;
                            break;

                        case '107':
                            $licence[ $product_id ]['activated']        = false;
                            $licence[ $product_id ]['message']          = $body['error'];
                            $licence[ $product_id ]['status_code']      = $body['code'];
                            //$licence[ $product_id ]['is_membership']    = isset( $body['is_membership'] ) ? $body['is_membership'] : false;
                            break;
                    }
                }

                /* === Update Plugin Licence Information === */
                update_option( $this->_licence_option, $licence );

                /* === Update Plugin Licence Information === */
                if( $regenerate_transient ) {
                    YIT_Upgrade()->force_regenerate_update_transient();
                }
            }
            return $status;
        }

        /**
         * Check for licence update
         *
         * @return void
         * @since 2.5
         *
         * @use YIT_Theme_Licence->check()
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function check_all(){
            foreach ( $this->_products as $init => $info ) {
                $this->check( $init );
            }
        }

         /**
         * Update Plugins Information
         *
         * Send a request to API server to check activate plugins and update the informations
         *
         * @return void
         * @use YIT_Theme_Licence->check()
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function update_licence_information() {
            /* Check licence information for alla products */
            $this->check_all();

            /* === Regenerate Update Plugins Transient === */
            YIT_Upgrade()->force_regenerate_update_transient();

            do_action( 'yit_licence_after_check' );

           if( $this->is_ajax() )  {
                $response['template'] = $this->show_activation_panel();
                wp_send_json( $response );
            }
        }

        /**
         * Include activation page template
         *
         * @return mixed void | string the contents of the output buffer and end output buffering.
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function show_activation_panel( $notice = '' ) {

            $path = defined( 'YIT_CORE_PLUGIN_PATH' ) ? YIT_CORE_PLUGIN_PATH : get_template_directory() . '/core/plugin-fw/';

            if ( $this->is_ajax() ) {
                ob_start();
                require_once( $path . '/licence/templates/panel/activation/activation-panel.php' );
                return ob_get_clean();
            }
            else {
                require_once( $path . '/licence/templates/panel/activation/activation-panel.php' );
            }
        }

        /**
         * Get activated products
         *
         * @return array
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_activated_products() {
            $activated_products = array();
            $licence           = $this->get_licence();

            if ( is_array( $licence ) ) {
                foreach ( $this->_products as $init => $info ) {
                    if ( in_array( $info['product_id'], array_keys( $licence ) ) && isset( $licence[$info['product_id']]['activated'] ) && $licence[$info['product_id']]['activated'] ) {
                        $product[$init]            = $this->_products[$init];
                        $product[$init]['licence'] = $licence[$info['product_id']];
                        $activated_products[$init] = $product[$init];
                    }
                }
            }

            return $activated_products;
        }

        /**
         * Get to active products
         *
         * @return array
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_to_active_products() {
            return array_diff_key( $this->get_products(), $this->get_activated_products() );
        }

        /**
         * Get no active products
         *
         * @return array
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_no_active_licence_key() {
            $unactive_products = $this->get_to_active_products();
            $licence          = $this->get_licence();
            $licence_key      = array();

            /**
             * Remove banned licence key
             */
            foreach ( $unactive_products as $init => $info ) {
                $product_id = $unactive_products[$init]['product_id'];
                if ( isset( $licence[$product_id]['activated'] ) && ! $licence[$product_id]['activated'] && isset( $licence[$product_id]['status_code'] ) ) {
                    $status_code = $licence[$product_id]['status_code'];

                    switch ( $status_code ) {
                        case '106':
                            $licence_key[$status_code][$init]            = $unactive_products[$init];
                            $licence_key[$status_code][$init]['licence'] = $licence[$product_id];
                            break;

                        case '107':
                            $licence_key[$status_code][$init]            = $unactive_products[$init];
                            $licence_key[$status_code][$init]['licence'] = $licence[$product_id];
                            break;
                    }
                }
            }
            return $licence_key;
        }

        /**
         * Get a specific product information
         *
         * @param $product_init | product init file
         *
         * @return mixed array
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_product( $init ) {
            return isset( $this->_products[$init] ) ? $this->_products[$init] : false;
        }

         /**
         * Get product product id information
         *
         * @param $product_init | product init file
         *
         * @return mixed array
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_product_id( $init ) {
            return isset( $this->_products[$init]['product_id'] ) ? $this->_products[$init]['product_id'] : false;
        }

        /**
         * Get Renewing uri
         *
         * @param $licence_key The licence key to renew
         *
         * @return mixed The renewing uri if licence_key exists, false otherwise
         *
         * @since    1.0
         * @author   Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_renewing_uri( $licence_key ) {
            return ! empty( $licence_key ) ? str_replace( 'www.', '', $this->_api_uri ) . '?renewing_key=' . $licence_key : false;
        }

        /**
         * Get protected yithemes api uri
         *
         * @param   $request
         *
         * @return mixed array
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_api_uri( $request ) {
            return str_replace( '%request%', $request, $this->_api_uri . $this->_api_uri_query_args );
        }

        /**
         * Get the activation page url
         *
         * @return String | Activation page url
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_licence_activation_page_url() {
            return esc_url( add_query_arg( array( 'page' => $this->_settings['page'] ), admin_url( 'admin.php' ) ) );
        }


        /**
         * Get the licence information
         *
         * @return array | licence array
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_licence() {
            return get_option( $this->_licence_option );
        }

        /**
         * Get the licence information
         *
         * @param $code string The error code
         *
         * @return string | Error code message
         *
         * @since  1.0
         * @author Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function get_response_code_message( $code, $args = array() ) {
            extract( $args );

            $messages = array(
                '100'           => __( 'Invalid Request', 'yith-plugin-fw' ),
                '101'           => __( 'Invalid license key', 'yith-plugin-fw' ),
                '102'           => __( 'Software has been deactivated', 'yith-plugin-fw' ),
                '103'           => __( 'Maximum number of activations exceeded', 'yith-plugin-fw' ),
                '104'           => __( 'Invalid instance ID', 'yith-plugin-fw' ),
                '105'           => __( 'Invalid security key', 'yith-plugin-fw' ),
                '106'           => __( 'License key has expired', 'yith-plugin-fw' ),
                '107'           => __( 'License key has been banned', 'yith-plugin-fw' ),
                '108'           => __( 'Current product is not included in your YITH Club Subscription key', 'yith-plugin-fw' ),
                '200'           => sprintf( '<strong>%s</strong>! %s',__( 'Great', 'yith-plugin-fw' ), __( 'License successfully activated', 'yith-plugin-fw' ) ),
                'deactivated'   => sprintf( '%s <strong>%s</strong>', __( 'License key deactivated for website', 'woocommerce-software-add-on' ), isset( $instance ) ? $instance : '' )
            );

            return isset( $messages[$code] ) ? $messages[$code] : false;
        }

        /**
         * Get the product name to display
         *
         * @param $product_name
         *
         * @return string the product name
         *
         * @since    2.2
         * @author   Andrea Grillo <andrea.grillo@yithemes.com>
         */
        public function display_product_name( $product_name ){
            return str_replace( array( 'for WooCommerce', 'YITH', 'WooCommerce', 'Premium', 'Theme', 'WordPress' ), '', $product_name );
        }

        public function get_number_of_membership_products(){
            $activated_products = $this->get_activated_products();
            $num_members_products_activate = 0;
            foreach( $activated_products as $activated_product ){
                if( isset( $activated_product['licence']['is_membership'] ) && $activated_product['licence']['is_membership'] ){
                    $num_members_products_activate++;
                }
            }
            return $num_members_products_activate;
        }

    }
}