<?php

// phpcs:ignore Standard.Category.SniffName.ErrorCode
namespace WPDataAccess\Dashboard;

use WPDataAccess\WPDA;
/**
 * Abstract widget base class
 */
abstract class WPDA_Widget {
    /**
     * Nonce seed
     */
    const WIDGET_ADD = 'WPDA_WIDGET_ADD';

    /**
     * Nonce seed
     */
    const WIDGET_REFRESH = 'WPDA_WIDGET_REFRESH';

    /**
     * Widget sequence number
     *
     * @var int
     */
    protected static $widget_sequence_nr = 0;

    /**
     * Active column number
     *
     * @var int|mixed
     */
    protected $column = 1;

    /**
     * Share indicator
     *
     * @var bool
     */
    protected $can_share = false;

    /**
     * Layout indicator
     *
     * @var bool
     */
    protected $has_layout = false;

    /**
     * Settings indicator
     *
     * @var bool
     */
    protected $has_setting = false;

    /**
     * Refresh indicator
     *
     * @var bool
     */
    protected $can_refresh = false;

    /**
     * Widget name
     *
     * @var mixed|string
     */
    protected $name = 'No name';

    /**
     * Widget title
     *
     * @var mixed|string
     */
    protected $title = 'No title';

    /**
     * Widget content
     *
     * @var mixed|string
     */
    protected $content = 'Loading...';

    /**
     * Nonce
     *
     * @var null
     */
    protected $wp_nonce = null;

    /**
     * Current widget id
     *
     * @var int|mixed
     */
    protected $widget_id = 0;

    /**
     * Widget positioning
     *
     * @var string
     */
    protected $position = 'append';

    /**
     * Current state
     *
     * @var mixed|string|null
     */
    protected $state = null;

    /**
     * Lock indicator
     *
     * @var bool
     */
    protected $is_locked = false;

    /**
     * Widget shares
     *
     * @var array
     */
    protected $share = array(
        'post'  => 'true',
        'page'  => 'true',
        'embed' => 'block',
        'allow' => array(),
    );

    /**
     * Constructor
     *
     * @param array $args Constructor arguments.
     */
    public function __construct( $args = array() ) {
        wp_enqueue_script( 'jquery-ui-widget' );
        if ( isset( $args['name'] ) ) {
            $this->name = $args['name'];
        }
        if ( isset( $args['column'] ) ) {
            $this->column = $args['column'];
        }
        if ( isset( $args['title'] ) ) {
            $this->title = $args['title'];
        }
        if ( isset( $args['content'] ) ) {
            $this->content = $args['content'];
        }
        if ( isset( $args['position'] ) && 'prepend' === $args['position'] ) {
            $this->position = 'prepend';
        }
        if ( isset( $args['widget_id'] ) ) {
            $this->widget_id = $args['widget_id'];
            // Used to add widgets via ajax.
        } else {
            $this->widget_id = ++self::$widget_sequence_nr;
            // Used to add widgets on page load.
        }
        if ( isset( $args['is_locked'] ) ) {
            $this->is_locked = true === $args['is_locked'] || 'true' === $args['is_locked'];
        }
        if ( isset( $args['share'] ) && isset( 
            $args['share']['roles'],
            $args['share']['users'],
            $args['share']['post'],
            $args['share']['page'],
            $args['share']['embed'],
            $args['share']['allow']
         ) ) {
            $this->share = array(
                'roles' => $args['share']['roles'],
                'users' => $args['share']['users'],
                'post'  => $args['share']['post'],
                'page'  => $args['share']['page'],
                'embed' => $args['share']['embed'],
                'allow' => $args['share']['allow'],
            );
        }
        $this->state = ( isset( $args['state'] ) ? $args['state'] : 'new' );
        $this->wp_nonce = wp_create_nonce( static::WIDGET_REFRESH . WPDA::get_current_user_login() );
    }

    /**
     * Construct widget container
     *
     * @return false|string
     */
    protected function container() {
        ob_start();
        ?>
			<script type="application/javascript" class="wpda-widget-<?php 
        echo esc_attr( $this->widget_id );
        ?>">
				jQuery(function() {
					var widget = `<?php 
        echo $this->html();
        // phpcs:ignore WordPress.Security.EscapeOutput
        ?>`;

					jQuery("#wpda-dashboard-column-<?php 
        echo esc_attr( $this->column );
        ?>").<?php 
        echo esc_attr( $this->position );
        ?>(widget);
					jQuery("#wpda-widget-<?php 
        echo esc_attr( $this->widget_id );
        ?>").data("name", "<?php 
        echo esc_attr( $this->name );
        ?>" );

					jQuery("#wpda-widget-<?php 
        echo esc_attr( $this->widget_id );
        ?> .wpda-widget-close").on("click", function() {
						removePanelFromDashboard(jQuery(this).closest('.wpda-widget'));
					});
				});
			</script>
			<?php 
        $this->js();
        return ob_get_clean();
    }

    /**
     * Construct widget html
     *
     * @return string
     */
    protected function html() {
        $share = '';
        $layout = '';
        $setting = '';
        $refresh = ( $this->can_refresh ? "<i class='fas fa-sync-alt wpda-widget-refresh wpda_tooltip' title='Refresh'></i> &nbsp;" : '' );
        $close = ( !$this->is_locked ? '<i class="fas fa-window-close wpda-widget-close wpda_tooltip" title="Close"></i>' : '' );
        $widget = <<<EOF
                <div id="wpda-widget-{$this->widget_id}" data-id="{$this->widget_id}" class="wpda-widget ui-widget">
                    <div class="wpda-widget-content">
                        <div class="ui-widget-header">
                            <span>{$this->name}</span>
                            <span class="icons">
\t\t\t\t\t\t\t\t{$share}
\t\t\t\t\t\t\t\t{$layout}
\t\t\t\t\t\t\t\t{$setting}
\t\t\t\t\t\t\t\t{$refresh}
\t\t\t\t\t\t\t\t{$close}
\t\t\t\t\t\t\t</span>
                        </div>
                        <div class="ui-widget-content">
                            {$this->content}
                        </div>
                    </div>
                </div>
EOF;
        return $widget;
    }

    /**
     * Cross origin check
     *
     * @param WPDA_Widget $widget Widget.
     * @return bool
     */
    protected static function check_cors( $widget ) {
        if ( isset( $_POST['wpda_caller'] ) && 'embedded' === $_POST['wpda_caller'] ) {
            // phpcs:ignore WordPress.Security.NonceVerification
            $share = ( isset( $widget['widgetShare'] ) ? $widget['widgetShare'] : null );
            if ( 'block' === $share['embed'] ) {
                WPDA::sent_header( 'application/json', '*' );
                echo static::msg( 'ERROR', 'No access' );
                // phpcs:ignore WordPress.Security.EscapeOutput
                wp_die();
            } else {
                if ( '*' === $share['embed'] ) {
                    WPDA::sent_header( 'application/json', '*' );
                    return true;
                } else {
                    // Access is already checked with sonce token.
                    WPDA::sent_header( 'application/json', '*' );
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Abstract method forcing each subclass to add its own specific javascript code
     *
     * @return mixed
     */
    protected abstract function js();

    // Method to add custom JavaScript code.
    /**
     * Add widget to dashboard
     *
     * @return void
     */
    public function add() {
        echo $this->container();
        // phpcs:ignore WordPress.Security.EscapeOutput
        ?>
			<script type="application/javascript">
				jQuery(function() {
					increaseWidgetSequenceNr();
				});
			</script>
			<?php 
    }

    /**
     * Abstract widget method forcing each subclass to implement its own specific widget functionality
     *
     * @return mixed
     */
    public static abstract function widget();

    /**
     * Construct widget via ajax (general part used for each widget)
     *
     * @return void
     */
    public static function ajax_widget() {
        $wp_nonce = ( isset( $_POST['wp_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['wp_nonce'] ) ) : '' );
        if ( !wp_verify_nonce( $wp_nonce, static::WIDGET_ADD . WPDA::get_current_user_login() ) ) {
            WPDA::sent_header( 'application/json' );
            echo static::msg( 'ERROR', 'Token expired, please refresh page' );
            // phpcs:ignore WordPress.Security.EscapeOutput
            wp_die();
        }
        static::widget();
    }

    /**
     * Abstract refresh method forcing each subclass to implement its own specific refresh functionality
     *
     * @return mixed
     */
    public static abstract function refresh();

    /**
     * Refresh widget via ajax (general part used for each widget)
     *
     * @return void
     */
    public static function ajax_refresh() {
        $wp_nonce = ( isset( $_POST['wp_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['wp_nonce'] ) ) : '' );
        if ( !wp_verify_nonce( $wp_nonce, static::WIDGET_REFRESH . WPDA::get_current_user_login() ) ) {
            WPDA::sent_header( 'application/json' );
            echo static::msg( 'ERROR', 'Token expired, please refresh page' );
            // phpcs:ignore WordPress.Security.EscapeOutput
            wp_die();
        }
        static::refresh();
    }

    /**
     * Construct JSON response message
     *
     * @param string $status Response status.
     * @param string $msg Response message.
     * @return mixed
     */
    protected static function msg( $status, $msg ) {
        $error = array(
            'status' => $status,
            'msg'    => $msg,
        );
        return wp_json_encode( $error );
    }

}
