<?php
/**
 * Please see wp-cookie-allow.php for more details.
 *
 * @author $Vincent Weber <weepie-plugins@outlook.com>$
 */

use WpieFw\Exceptions\WpieExceptionInterface;

if( ! defined( 'ABSPATH' ) ) exit;

if( !class_exists( 'WpcaModuleCcpa' ) ) {
    /**
     * WpcaModuleCcpa Class
     *
     * Module to handle the CCPA logic
     *
     * @author $Vincent Weber <weepie-plugins@outlook.com>$
     *
     * @since 3.2.11
     */
    class WpcaModuleCcpa extends WpieFw\Modules\Iterator\WpieModule
    {
        /**
         * Country ISO code for United States
         *
         * @var string
         *
         * @since 3.2.11
         */
        const COUNTRY_ISOCODE_US = 'US';

        /**
         * United States state California name
         *
         * @var string
         *
         * @since 3.2.11
         */
        const SUBDIV_NAME_STATE_CALIFORNIA = 'California';

        /**
         * Template file name for the DNSMPI page link
         *
         * @since 3.2.11
         *
         * @var string
         */
        const TEMPL_FILE_NAME_DNSMPI_LINK = 'wpca-ccpa-link-dnsmpi.php';

        /**
         * Module priority
         *
         * Must be lower then WpcaCore (5)
         *
         * @var integer
         *
         * @since 3.2.11
         */
        protected $priority = 3;

        /**
         * CSS class for the DNSMPI page link
         *
         * since 3.2.11
         *
         * @var string
         */
        private $dnsmpiCssClass = 'wpca-dnsmpi-link';

        /**
         * Privacy page Post ID
         *
         * @since 3.2.11
         *
         * @var int
         */
        private $dnsmpiPageId = 0;

        /**
         * Flag if CCPA logic needs to be applied
         *
         * @var string
         *
         * @since 3.2.11
         */
        private $doCCPALogic = false;

        /**
         * Settings value for ccpa_enable
         *
         * @var boolean
         *
         * @since 3.2.11
         */
        public $enableCCPA = false;

        /**
         * Flag if a DNSMPI page is present
         *
         * @since 3.0
         *
         * @var bool
         */
        public $hasDnsmpiPage = false;

        /**
         * Flag if DNSMPI page is a PDF
         *
         * @since 3.2.11
         *
         * @var bool
         */
        public $dnsmpiIsPdf = false;

        /**
         * URL to the DNSMPI page
         *
         * since 3.2.11
         *
         * @var string
         */
        public $dnsmpiUrl = '';

        /**
         * Relative URL to the DNSMPI page
         *
         * since 3.2.11
         *
         * @var string
         */
        public $dnsmpiUrlRel = '';

        /**
         * Flag if the bar/box should be displayed on the DNSMPI page
         *
         * @since 3.2.11
         *
         * @var string
         */
        public $showBarBoxOnDnsmpiPage = false;

        /**
         * {@inheritDoc}
         * @see \WpieFw\Modules\Iterator\WpieModule::start()
         */
        public function start()
        {
            add_filter( 'wpca_setting_groups', array( $this, 'modifySettingsGroups' ) );
        }

        /**
         * Callback for the wpca_script_frontend_vars_before hook
         *
         * @access public
         *
         * @param array $vars
         *
         * @since 3.2.11
         * @since 3.4.5 renamed to setScriptVars
         *
         * @return array
         */
        public function setScriptVars( $vars )
        {
            // overwrite module frontend vars
            $vars['useXAsDismiss']        = false;
            $vars['hasClose']             = $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_show_x' );
            $vars['cookiesBeforeConsent'] = $this->getModule( 'core' )->cookiesBeforeConsentId3rdParties;

            // CCPA specific settings
            $vars['ccpa'] = array();
            $vars['ccpa']['dnsmpiCssClass']  = $this->dnsmpiCssClass;
            $vars['ccpa']['dnsmpiUrlRel']    = $this->dnsmpiUrlRel;
            $vars['ccpa']['consentAfterUse'] = $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_hide_bar_box_after_using' );
            $vars['ccpa']['showBtnAccept']   = $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_show_btn_accept' );
            $vars['ccpa']['showBtnDecline']  = $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_show_btn_decline' );

            return $vars;
        }

        /**
         * Callback for the wpca_registered_shortcodes hook
         *
         * Register the shortcodes for this module
         *
         * @param array $registered
         *
         * @since 3.2.11
         *
         * @return array
         */
        public function registerShortcodes( $registered = array() )
        {
            $shordcodes = array(
                'wpca_ccpa_dnsmpi_link' => 'doShortcodeDnsmpiLink',
            );

            foreach ( $shordcodes as $shordcode => $callback ) {
                $registered[] = $shordcode;

                if( !defined( 'WPCA_ACTIVE' ) ) {
                    $callback = array( 'WpieFw\Helpers\WpieMiscHelper', 'doShortcodeNot' );
                } else {
                    $callback = array( $this, $callback );
                }

                add_filter( 'wpca_shortcode_' . $shordcode, $callback, 10, 3 );
            }

            return $registered;
        }

        /**
		 * Callback for the wpca_shortcode_wpca_ccpa_dnsmpi_link hook
		 *
		 * Render the shortcode content
		 *
		 * @access public
		 *
		 * @param array $atts
		 * @param string $content
		 * @param string $tag
		 *
		 * @uses WpcaFrontend::renderLinkPolicy()
		 *
		 * @since 3.2.11
		 *
		 * @return string
         */
        public function doShortcodeDnsmpiLink( $atts = array(), $content = '', $tag = '' )
        {
            if( !$this->hasDnsmpiPage ) {
                return '';
            }

            $atts = shortcode_atts(
                array(
                    'txt' => $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_dnsmpi_link_text' ),
                    'class' => $this->dnsmpiCssClass,
                    'target' => $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_dnsmpi_page_target' )
                ), $atts, $tag );

            $atts['href'] = $this->dnsmpiUrl;

            /** @var WpcaModuleFrontend $moduleFrontend */
            $moduleFrontend = $this->getModule( 'frontend' );
            return $moduleFrontend->renderLinkPolicy( $atts );
        }

        /**
         * Callback for the hook
         *
         * Modify the $tabs array to capitalize the Ccpa menu title
         *
         * @param array $tabs
         *
         * @since 3.2.11
         *
         * @param array $tabs
         * @return array
         */
        public function modifySettingsGroups( $tabs = array() )
        {
            if( isset( $tabs['ccpa'] ) && isset( $tabs['ccpa']['tab'] ) ) {
                $tabs['ccpa']['tab'] = strtoupper( $tabs['ccpa']['tab'] );
            }

            return $tabs;
        }

        /**
         * Callback for the wpca_instantiate_layout_template hook
         *
         * Add CCPA logic to the bar or box
         *
         * @param array $vars
         * @param string $layout
         *
         * @since 3.2.11
         *
         * @return array
         */
        public function modifyLayoutTemplateVars( $vars, $layout )
        {
            $vars['showIconClose'] = $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_show_x' );
            $vars['text'] = $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_noc_text' );
            $vars['showBtnAccept'] = $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_show_btn_accept' );
            $vars['showBtnDecline'] = $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_show_btn_decline' );
            $vars['btnAcceptTxt'] = $this->settingsProcessor->get('ccpa')->get( 'ccpa_button_accept_txt' );
            $vars['btnDeclineTxt'] = $this->settingsProcessor->get('ccpa')->get( 'ccpa_button_decline_txt' );

            return $vars;
        }

        /**
         * Callback for the wpca_do_frontend_logic hook
         *
         * Force the frontend logic when $reason is 3 (disable For Non EU & IP address is NOT from the EU)
         *
         * @since 3.2.11
         *
         * @return boolean
         */
        public function doFrontendLogic( $do, $reason )
        {
            if( 3 === $reason && $this->doCCPALogic ) {
                $do = true;
            }

            return $do;
        }

        /**
         * Determine if CCPA logic is needed
         *
         * @since 3.2.11
         *
         * @return boolean
         */
        public function isCCPALogicNeeded()
        {
            return ( defined( 'WPCA_ACTIVE' ) && $this->enableCCPA && $this->doCCPALogic );
        }

        /**
         * Determine if current user IP address is from California
         *
         * @uses WpcaModuleGeo::fetch()
         *
         * @throws Throwable
         * @throws Exception
         *
         * @since 3.2.11
         *
         * @return boolean|null
         */
        public function isIpAddressFromCalifornia()
        {
            static $is = null;

            if( null !== $is ) {
                return $is;
            }

            // Let WeePie Framework handle Exceptions
            try {
                // if having a valid $record, continue
                /** @var WpcaModuleGeo $moduleGeo */
                $moduleGeo = $this->getModule( 'geo' );
                if( $record = $moduleGeo->fetch( 'city' ) ) {
                    // Flag if the current IP address is from Unites states California
                    $is = ( self::COUNTRY_ISOCODE_US === $record->country->isoCode && self::SUBDIV_NAME_STATE_CALIFORNIA === $record->mostSpecificSubdivision->name );
                }
            } catch ( \Throwable $e ) {
                throw $e;
            } catch( \Exception $e ) {
                throw $e;
            }

            /**
             * Filter if the result recored is from the Unites states California
             *
             * @var bool $is
             * @var \GeoIp2\Model\City $record
             *
             * @since 3.2.11
             */
            return apply_filters( 'wpca_geoip_is_from_california', $is, $record );
        }


		/**
		 * Setup the parameters for the frontend logic
		 *
		 * @since 3.4
		 */
		public function initParams()
		{
            if( $this->doCCPALogic ) {
                // the DNSMPI page
                $this->dnsmpiPageId = (int)$this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_dnsmpi_page' );
                $this->hasDnsmpiPage = ( -1 !== $this->dnsmpiPageId );
                if( $this->hasDnsmpiPage ) {
                    $this->dnsmpiIsPdf = ( wp_attachment_is( 'pdf', $this->dnsmpiPageId ) );
                    if( !$this->dnsmpiIsPdf ) {
                        // show or hide the bar/box on the cookie policy page
                        $this->showBarBoxOnDnsmpiPage = $this->settingsProcessor
                        ->get( 'ccpa' )
                        ->get( 'ccpa_show_bar_box_dnsmpi_page' );

                        // the cookie policy page URL
                        $dnsmpiUrl = get_page_link( $this->dnsmpiPageId );

                        if( $this->showBarBoxOnDnsmpiPage ) {
                            $this->dnsmpiUrl = $dnsmpiUrl;
                            $this->dnsmpiUrlRel = wp_make_link_relative( $this->dnsmpiUrl );
                        } else {
                            $this->dnsmpiUrl = add_query_arg( array( WpcaModuleFrontend::QUERY_VAR_BYPASS_COOKIE_CONSENT => '1' ), $dnsmpiUrl );
                        }
                    } else {
                        $this->dnsmpiUrl = wp_get_attachment_url( $this->dnsmpiPageId );
                    }
                }
            }
        }


        /**
         * Callback for the wpca_init_frontend_only_hooks hook
         *
         * @since 3.2.11
         */
        public function initHooksFrontend()
        {
              if( !$this->isCCPALogicNeeded() ) {
                return;
            }

            if( $this->doCCPALogic ) {
                $this->initParams();

                // only add script vars if CCPA logic is needed
                add_filter( 'wpca_script_frontend_vars_before', array( $this, 'setScriptVars' ), 100 );                
            }
        }

        /**
         * {@inheritDoc}
         * @see \WpieFw\Modules\Iterator\WpieModuleInterface::init()
         */
        public function init()
        {
            if( false === $this->settingsProcessor->get( 'ccpa' ) ) {
                return;
            }

            // The admin settin value for ccpa_enable
            $this->enableCCPA = $this->settingsProcessor->get( 'ccpa' )->get( 'ccpa_enable' );

            if( $this->enableCCPA && $this->doCCPALogic = $this->isIpAddressFromCalifornia() ) {
                // If user has enabled "Disable for non-EU visitors"
                // and CCPA logic is also enabled, force the frontend logic
                add_filter( 'wpca_do_frontend_logic', array( $this, 'doFrontendLogic' ), 10, 2 );

                add_action( 'wpca_before_render', function( $layout ) {
                    add_filter( 'wpca_instantiate_layout_template', array( $this, 'modifyLayoutTemplateVars' ), 1, 2 );
                } );
            }

			// register shortcodes for both admin (ajax) requests and frontend
			add_filter( 'wpca_registered_shortcodes', array( $this, 'registerShortcodes' ) );

            // apply hooks for frontend only
            add_action( 'wpca_init_frontend_only_hooks', array( $this, 'initHooksFrontend') );
        }
    }

    if( !function_exists( 'wpca_is_ccpa_logic_needed' ) )
    {
        /**
         * Determine if CCPA logis is needed
         *
         * @uses WpcaGeo::isCCPALogicNeeded()
         *
         * @since 3.2.11
         *
         * @return boolean
         */
        function wpca_is_ccpa_logic_needed()
        {
            if( false !== ( $module = \WpieFw\modules\WpieModuleProcessor::getModule( 'wpca', 'ccpa' ) ) )
            {
                /** @var WpcaModuleCcpa $module */
                $is = $module->isCCPALogicNeeded();
                unset( $module );

                return $is;
            }
        }
    }
}