<?php
/**
 * Contacter
 * Voice feedback form for your website for saving and transcribing user voice messages to text.
 * Exclusively on https://1.envato.market/contacter
 *
 * @encoding        UTF-8
 * @version         1.7.8
 * @copyright       (C) 2018 - 2023 Merkulove ( https://merkulov.design/ ). All rights reserved.
 * @license         Envato License https://1.envato.market/KYbje
 * @contributors    Dmitry Merkulov (dmitry@merkulov.design)
 * @support         help@merkulov.design
 **/

namespace Merkulove\Contacter;

use Exception;
use Merkulove\Contacter\Unity\Plugin;
use Merkulove\Contacter\Unity\Settings;
use WP_Post;
use WP_Query;

/** Exit if accessed directly. */
if ( ! defined( 'ABSPATH' ) ) {
	header( 'Status: 403 Forbidden' );
	header( 'HTTP/1.1 403 Forbidden' );
	exit;
}

/**
 * SINGLETON: Class used to add contacter_record post type.
 *
 * @since 1.0.0
 *
 **/
final class ContacterRecord {

	/**
	 * contacter_record Post Type name.
	 *
	 * @const POST_TYPE
	 * @since 1.0.0
	 **/
	const POST_TYPE = 'contacter_record';

	/**
	 * The one true ContacterRecord.
	 *
	 * @var ContacterRecord
	 * @since 1.0.0
	 **/
	private static $instance;

	/**
	 * Sets up a new instance.
	 *
	 * @since 1.0.0
	 * @access public
	 **/
	private function __construct() {

		/** Fire meta box setup on the post editor screen. */
		add_action( 'load-post.php', [ $this, 'meta_boxes_setup' ] );
		add_action( 'load-post-new.php', [ $this, 'meta_boxes_setup' ] );

		/** Add Transcription and Form columns to Contacter Form list. */
		add_filter( 'manage_' . self::POST_TYPE . '_posts_columns', [$this, 'columns_head'], 10 );
		add_action( 'manage_' . self::POST_TYPE . '_posts_custom_column', [$this, 'columns_body'], 10, 2 );

        /** Rename Publish button to Update. */
		add_filter( 'gettext', [$this, 'change_publish_button'], 10, 2 );

		/** Add new records notification. */
		add_action( 'admin_menu', [$this, 'add_notification'] );

		/** Create filter by Form dropdown. */
		add_action( 'restrict_manage_posts', [$this, 'create_filter_by_form']  );

		/** Filter by Form function. */
		add_filter( 'parse_query', [$this, 'filter_by_form'] );

		/** Remove audio files on remove contacter_record. */
		add_action( 'before_delete_post', [$this, 'before_delete_post'] );

	}

	/**
	 * Remove old audio on remove contacter_record.
	 *
	 * @param $post_id - The post id that is being deleted.
	 *
	 * @since 1.0.0
	 * @access public
	 **/
	public function before_delete_post( $post_id ) {

		/** Process only contacter_record posts. */
		if ( ContacterRecord::POST_TYPE !== get_post_type( $post_id ) ) { return; }

		/** Get audio file. */
		$audio_file_path = get_post_meta( $post_id, 'mdp_contacter_audio', true );

		/** Remove audio file. */
		if ( $audio_file_path ) {
			wp_delete_file( $audio_file_path );
		}

        /** Fire event to send email notification on delete. */
		do_action( 'contacter_record_removed', $post_id );

	}

	/**
	 * If submitted filter by Form.
	 *
	 * @param $query
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @return void
	 **/
	public function filter_by_form( $query ) {
		global $pagenow;

		/** Work only for contacter_record post type. */
		$type = self::POST_TYPE;
		if ( isset( $_GET['post_type'] ) ) {
			$type = $_GET['post_type'];
		}

		/** Modify query to filter records. */
		if (
			self::POST_TYPE === $type &&
			is_admin() &&
			$pagenow ==='edit.php' &&
			isset( $_GET['mdp-contacter-filter-by-form'] ) &&
			$_GET['mdp-contacter-filter-by-form'] !== ''
		) {
			$query->query_vars['meta_key'] = 'mdp_cform_id';
			$query->query_vars['meta_value'] = $_GET['mdp-contacter-filter-by-form'];
		}

	}

	/**
	 * Create filter by Form dropdown.
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @return void
	 **/
	public function create_filter_by_form() {

		/** Work only for contacter_records post type. */
		$type = self::POST_TYPE;
		if ( isset( $_GET['post_type'] ) ) {
			$type = $_GET['post_type'];
		}

		if ( self::POST_TYPE !== $type ) { return; }

		/** Get all Contacter forms. */
		$wp_query = new WP_Query;
		$query = [
			'post_type' => ContacterForm::POST_TYPE,
			'post_status' => ['publish']
		];
		$c_forms = $wp_query->query( $query );

		$values = [];
		foreach ( $c_forms as $c_form ) {
			$values[$c_form->ID] = $c_form->post_title;
		}

		?>
        <!--suppress HtmlFormInputWithoutLabel -->
		<select name="mdp-contacter-filter-by-form">
            <option value=""><?php esc_html_e( 'Filter By Form', 'contacter' ); ?></option>
			<?php
			$current_v = isset( $_GET['mdp-contacter-filter-by-form'] ) ? $_GET['mdp-contacter-filter-by-form'] : '';
			foreach ( $values as $cform_id => $title ) {
				?>
                <option value="<?php esc_attr_e( $cform_id ); ?>" <?php echo ( $cform_id === $current_v ) ? ' selected' : '' ?>>
					<?php esc_html_e( $title ); ?>
                </option>
				<?php
			}
			?>
        </select>
		<?php
	}

	/**
	 * Add content for Transcription and Form columns.
	 *
	 * @param $column_name
	 * @param $record_id
	 *
	 * @throws Exception
	 * @since  1.0.0
	 * @access public
	 **/
	public function columns_body( $column_name, $record_id ) {

        $options = Settings::get_instance()->options;

        /** Record ID */
		if ( 'mdp_contacter_record_id' === $column_name ) {

            echo wp_sprintf(
                '<div class="mdp-record-id">%s</div>',
                get_the_ID()
            );

        }

        /** Location column */
		if ( 'mdp_contacter_record_location' === $column_name ) {

            $ip             = get_post_meta( $record_id, 'contacter_ip', true );
			$country        = get_post_meta( $record_id, 'contacter_country', true );
			$country_name   = apply_filters( 'contacter_country', get_post_meta( $record_id, 'contacter_country_name', true ) );
			$city           = get_post_meta( $record_id, 'contacter_city', true );

            if ( $ip === '' ) { return; }

			echo wp_sprintf(
				'<div class="mdp-user-info">
                                <img src="%2$s" alt="%3$s, %4$s">
                                <span><b>%3$s, %4$s</b> (%1$s)</span>
                            </div>',
				$ip,
				Plugin::get_url() . '/images/flags/'. strtolower( $country ) . '.svg',
				$country_name,
				$city
			);

		}

		/** Transcription column. */
		if ( $options['speech_recognition'] === 'on' && 'mdp_contacter_record_transcription' === $column_name  ) {

			/** Get Contacter Record Transcription. */
			$transcription = get_post_meta( $record_id, 'mdp_transcription_txt', true );
            echo wp_kses_post( $transcription );

		}

		/** Form column. */
		if ( 'mdp_contacter_record_form' === $column_name ) {

			/** Get Contacter Form ID. */
			$cform_id = get_post_meta( $record_id, 'mdp_cform_id', true );
			$cform = get_post( $cform_id );
			if ( $cform === null ) { return; }

			?><a class="mdp-contacter-record-form" href="<?php echo admin_url( 'post.php?post=' . $cform->ID . '&action=edit&classic-editor' ); ?>"><?php esc_html_e( $cform->post_title ); ?></a><?php

		}

	}

	/**
	 * Add Transcription and Form columns.
	 *
	 * @param array $columns
	 *
	 * @return array
	 * @since 1.0.0
	 * @access public
	 **/
	public function columns_head( $columns ) {

        $options = Settings::get_instance()->options;

		/** Add new column key to the existing columns. */

		if ( $options[ 'show_record_id' ] === 'on' ) {
			$columns['mdp_contacter_record_id'] = esc_html__( 'ID', 'contacter' );
		}

		$columns['mdp_contacter_record_location'] = esc_html__( 'Location', 'contacter' );

        if ( $options['speech_recognition'] === 'on' ) {
	        $columns['mdp_contacter_record_transcription'] = esc_html__( 'Transcription', 'contacter' );
        }

		$columns['mdp_contacter_record_form'] = esc_html__( 'Form', 'contacter' );

		/** Define a new order */

		$new_order = ['cb', 'title', 'mdp_contacter_record_location', 'mdp_contacter_record_form', 'date'];

        if ( $options['speech_recognition'] === 'on'  ) {

	        array_splice(
                $new_order,
                3,
                0,
                array( 'mdp_contacter_record_transcription' )
            );

        }

		if ( $options[ 'show_record_id' ] === 'on' ) {

			array_splice(
				$new_order,
				1,
				0,
				array( 'mdp_contacter_record_id' )
			);

        }

		/** Order columns like set in $new_order. */
		$new = [];
		foreach ( $new_order as $col_name ) {
			$new[ $col_name ] = $columns[ $col_name ];
		}

		/** Return a new column array to WordPress. */
		return $new;
	}

	/**
	 * Add new contacter_record notification.
	 *
	 * @since  1.0.0
	 * @access public
	 * @return void
	 **/
	public function add_notification() {
		global $menu;

		/** Count contacter_records posts. */
		$count = wp_count_posts( self::POST_TYPE );
		$count = $count->pending;

		if ( $count > 0 ) {
			$menu_item = wp_list_filter(
				$menu,
				[2 => 'edit.php?post_type=contacter_record'] // 2 is the position of an array item which contains URL, it will always be 2!
			);

			if ( ! empty( $menu_item )  ) {
				$menu_item_position = key( $menu_item ); // get the array key (position) of the element
				$menu[ $menu_item_position ][0] .= ' <span class="awaiting-mod">' . $count . '</span>';
			}
        }
	}

	/**
	 * Rename Publish button to Update for Contacter Record.
	 *
	 * @param string $translation - Translated text.
	 * @param string $text - Text to translate.
	 *
	 * @since  1.0.0
	 * @access public
	 * @return string
	 **/
	public function change_publish_button( $translation, $text ) {

	    /** Work only with contacter_record. */
		if ( self::POST_TYPE !== get_post_type() ) { return $translation; }

		if ( $text == 'Publish' ) {
			return 'Update';
        }

		return $translation;
    }

	/**
	 * Meta box setup function.
	 *
	 * @since 1.0.0
	 * @access public
	 **/
	public function meta_boxes_setup() {

		/** Add meta boxes on the 'add_meta_boxes' hook. */
		add_action( 'add_meta_boxes', [ $this, 'add_meta_boxes' ] );

		/** Save meta box values on the 'save_post' hook. */
		add_action( 'save_post', [ $this, 'save_meta_boxes' ], 1, 2 );

	}

	/**
	 * Save meta box values.
	 *
	 * @param $post_id
	 * @param $post
	 *
	 * @return void
	 * @since 1.0.0
	 * @access public
	 **/
	public function save_meta_boxes( $post_id, $post ) {

		/** Work only with contacter_form post type. */
		if ( 'contacter_record' !== $post->post_type ) { return; }

		/** Verify the nonce before proceeding. */
		if (
			! isset( $_POST['options_metabox_fields_nonce'] ) ||
			! wp_verify_nonce( $_POST['options_metabox_fields_nonce'], Plugin::get_basename() )
		) {
			return;
		}

		/** Get the post type object. */
		$post_type = get_post_type_object( $post->post_type );

		/** Check if the current user has permission to edit the post. */
		if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) { return; }

		/** Save metaboxes with all fields. */
		CROptionsMetaBox::get_instance()->save_metabox( $post_id );

	}

	/**
	 * Create Options, Shortcode and Messages meta boxes to be displayed on Contacter Form editor screen.
	 *
	 * @since 1.0.0
	 * @access public
	 **/
	public function add_meta_boxes() {

		/** Options metabox. */
		add_meta_box( 'mdp-options-mbox', esc_html__( 'Record Options', 'contacter' ), [$this, 'options_metabox'], self::POST_TYPE, 'normal', 'default' );

		/** Notes metabox. */
		add_meta_box( 'mdp-notes-mbox', esc_html__( 'Private Notes', 'contacter' ), [$this, 'notes_metabox' ], self::POST_TYPE, 'normal', 'default' );

		/** Form Settings metabox. */
		add_meta_box( 'mdp-form-settings-mbox', esc_html__( 'Form Settings', 'contacter' ), [$this, 'form_settings_metabox'], self::POST_TYPE, 'side', 'default' );

	}

	/**
	 * Display Options meta box.
	 *
	 * @param WP_Post $contacter_record
	 *
	 * @since 1.0.0
	 *
	 * @access public
	 **/
	public function options_metabox( $contacter_record ) {

		/** Render "Options" metabox with all fields. */
		CROptionsMetaBox::get_instance()->render_metabox( $contacter_record );

	}

	/**
	 * Display Form Settings meta box.
	 *
	 * @param WP_Post $contacter_record
	 **/
	public function form_settings_metabox( $contacter_record ) {

		/** Get Contacter Form for current Record. */
		$cform_id = get_post_meta( $contacter_record->ID, 'mdp_cform_id', true );

		?><p><a href="<?php echo admin_url( 'post.php?post=' . $cform_id . '&action=edit&classic-editor' ); ?>"><?php esc_html_e( 'Go to Form Settings', 'contacter' ); ?></a></p><?php

	}

	/**
	 * Display Notice meta box.
	 *
	 * @param WP_Post $contacter_record
	 **/
	public function notes_metabox( $contacter_record ) {

		/** Get Notes Text field value from meta if it's already been entered. */
		$notes = get_post_meta( $contacter_record->ID, 'mdp_notes_txt', true );

		/** Default value. */
		if ( empty( $notes ) ) { $notes = ''; }

		wp_editor( $notes, 'mdpnotestxt', [
			'media_buttons' => 0,
			'teeny' => 1,
			'textarea_rows' => 5,
			'textarea_name' => 'mdp_notes_txt'
		] );

	}

	/**
	 * Register post type.
	 *
	 * @since 1.0.0
	 * @access public
	 **/
	public function register_post_type() {

		register_post_type( self::POST_TYPE, [
			'public'              => false,
			'labels'              => [
				'name'                  => esc_html__( 'Contacter Records', 'contacter' ),
				'singular_name'         => esc_html__( 'Contacter Records', 'contacter' ),
				'add_new'               => esc_html__( 'Add New', 'contacter' ),
				'add_new_item'          => esc_html__( 'Add New', 'contacter' ),
				'new_item'              => esc_html__( 'New Contacter Record', 'contacter' ),
				'edit_item'             => esc_html__( 'Edit Contacter Record', 'contacter' ),
				'view_item'             => esc_html__( 'View Contacter Record', 'contacter' ),
				'view_items'            => esc_html__( 'View Contacter Record', 'contacter' ),
				'search_items'          => esc_html__( 'Search Contacter Records', 'contacter' ),
				'not_found'             => esc_html__( 'No Contacter Records found', 'contacter' ),
				'not_found_in_trash'    => esc_html__( 'No Contacter Records found in Trash', 'contacter' ),
				'all_items'             => esc_html__( 'Records', 'contacter' ),
				'archives'              => esc_html__( 'Contacter Records Archives', 'contacter' ),
				'attributes'            => esc_html__( 'Contacter Record Attributes', 'contacter' ),
				'insert_into_item'      => esc_html__( 'Insert to Contacter Record', 'contacter' ),
				'uploaded_to_this_item' => esc_html__( 'Uploaded to this Contacter Record', 'contacter' ),
				'menu_name'             => esc_html__( 'Contacter', 'contacter' ),
			],
			'menu_icon'             => $this->get_svg_icon(),
			'exclude_from_search'   => true,
			'publicly_queryable'    => false,
			'menu_position'         => false,
			'show_in_rest'          => false,
			'rest_base'             => self::POST_TYPE,
			'supports'              => [ 'title' ],
			'capabilities'          => [ 'create_posts' => false ],
			'map_meta_cap'          => true,
			'show_ui'               => true,
		] );

	}

	/**
	 * Return base64 encoded SVG icon.
	 *
	 * @since 1.0.0
	 * @access public
	 **/
	public function get_svg_icon() {

		$svg = file_get_contents( Plugin::get_path() . 'images/logo-menu.svg' );

		return 'data:image/svg+xml;base64,' . base64_encode( $svg );
	}

	/**
     * Create /wp-content/uploads/contacter/ folder for audio files
	 * @return void
	 */
	public static function create_directory() {

		wp_mkdir_p( trailingslashit( wp_upload_dir()['basedir'] ) . 'contacter' );

	}

	/**
	 * Main ContacterRecord Instance.
	 *
	 * Insures that only one instance of ContacterRecord exists in memory at any one time.
	 *
	 * @static
	 * @return ContacterRecord
	 * @since 1.0.0
	 **/
	public static function get_instance() {
		if ( ! isset( self::$instance ) && ! ( self::$instance instanceof ContacterRecord ) ) {
			self::$instance = new ContacterRecord;
		}

		return self::$instance;
	}

} // End Class ContacterRecord.
