<?php
/**
 * Base class for Nisje Components.
 *
 * @package Nisje
 */

namespace Dekode\Nisje\Components;

defined( 'ABSPATH' ) || die( 'Shame on you' );

/**
 * The class.
 */
abstract class Component {
	/**
	 * Component name
	 *
	 * @var string $name
	 */
	public $name;

	/**
	 * Component label.
	 *
	 * @var string $label
	 */
	public $label;

	/**
	 * Component path.
	 *
	 * @var string $path
	 */
	public $path;

	/**
	 * Settings key.
	 *
	 * @var string
	 */
	public $settings_key = '';

	/**
	 * Option key.
	 *
	 * @var string
	 */
	public $option_key = '';

	/**
	 * Settings.
	 *
	 * @var array
	 */
	public $settings = [];

	/**
	 * Settings.
	 *
	 * @var array
	 */
	public $public_settings = [];

	/**
	 * Initiate component.
	 *
	 * @param string $name         Name.
	 * @param string $label        Label.
	 * @param string $path         Path.
	 * @param string $settings_key Custom settings key.
	 * @param string $option_key   Custom option key.
	 */
	public function start( $name, $label, $path = '', $settings_key = '', $option_key = '' ) {
		$this->name  = sanitize_key( $name );
		$this->label = esc_html( $label );
		$this->path  = $path;

		if ( ! empty( $option_key ) ) {
			$this->option_key = sanitize_key( $option_key );
		} else {
			$this->option_key = 'nisje-' . $this->name . '-settings';
		}

		if ( ! empty( $settings_key ) ) {
			$this->settings_key = sanitize_key( $settings_key );
		} else {
			$this->settings_key = str_replace( '-', '_', $this->name );
		}

		// Move on to the next step.
		$this->setup_core_actions();
	}

	/**
	 * Setup actions.
	 */
	private function setup_core_actions() {
		$this->add_component_action( 'nisje_register_content_types', [ $this, 'register_content_types' ], 10 );
		$this->add_component_action( 'nisje_register_rest_routes', [ $this, 'register_rest_routes' ], 10 );
		$this->add_component_action( 'nisje_component_updates', [ $this, 'updates' ], 10 );
		$this->add_component_action( 'nisje_add_public_component_settings', [ $this, 'register_public_settings' ], 10 );

		add_filter( 'nisje_add_public_component_settings', [ $this, 'handle_public_component_settings' ], 10 );
		add_filter( 'nisje_extend_settings', [ $this, 'register_settings' ], 10 );
	}

	/**
	 * Check if function exists before calling the filter
	 *
	 * @param  string $tag             Filter to call.
	 * @param  string $function_to_add Function to bind to filter.
	 * @param  int    $priority        Priority of the filter.
	 * @param  int    $accepted_args   Accepted arguments.
	 * @return void
	 */
	private function add_component_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
		if ( is_callable( $function_to_add ) ) {
			add_filter( $tag, $function_to_add, $priority, $accepted_args );
		}
	}

	/**
	 * Check if function exists before calling the action
	 *
	 * @param  string $tag             Filter to call.
	 * @param  string $function_to_add Function to bind to filter.
	 * @param  int    $priority        Priority of the filter.
	 * @param  int    $accepted_args   Accepted arguments.
	 * @return void
	 */
	private function add_component_action( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
		if ( is_callable( $function_to_add ) ) {
			add_action( $tag, $function_to_add, $priority, $accepted_args );
		}
	}

	/**
	 * Handle public settings.
	 */
	public function handle_public_component_settings() {
		if ( is_callable( 'register_public_settings' ) ) {
			$this->register_public_settings();
		}

		$this->public_settings = apply_filters( 'nisje_add_public_component_settings_' . $this->name, $this->public_settings );
	}

	/**
	 * Register Settings
	 *
	 * @param array $settings Settings.
	 */
	public function register_settings( $settings ) {
		$extend_settings = [
			$this->settings_key => $this->settings,
		];

		return array_merge( $extend_settings, $settings );
	}

	/**
	 * Helper for including files relative to component.
	 *
	 * @param string $path Path of file relative to current component.
	 */
	public function include_file( $path ) {
		$path = $this->path . $path;

		if ( file_exists( $path ) ) {
			include_once $path;
		}
	}

	/**
	 * Helper for saving options.
	 */
	public function save_options() {
		update_option( $this->option_key, $this->settings );
	}
}
