<?php

/**
 * Displays all global posts as default WP admin list table
 *
 * @extends WP_List_Table ( wp-admin/includes/class-wp-list-table.php )
 */

namespace Greyd;

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

// include the parent class
if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

class Theme_Posts_List_Table extends \WP_List_Table {

	/**
	 * Posts per page
	 *
	 * default is 20.
	 */
	public $posts_per_page = 20;

	/**
	 * Displayed post type.
	 */
	private $post_type;

	/**
	 * Class constructor
	 */
	public function __construct() {
		parent::__construct(
			array(
				'singular' => 'theme-post-table',
				'plural'   => 'theme-post-table',
				'ajax'     => false,
			)
		);

		// remove the first char '_' from argument
		$posttype = isset( $_GET['post_type'] ) ? substr( $_GET['post_type'], 1 ) : '';

		if ( in_array( $posttype, Theme_Posts_Helper::get_supported_post_types() ) ) {
			$this->post_type = $posttype;
		} else {
			$this->post_type = Theme_Posts_Helper::get_supported_post_types();
		}
	}

	/**
	 * Handles data query and filter, sorting, and pagination.
	 */
	function prepare_items() {

		// process bulk action
		$this->process_bulk_action();

		// Define the columns and data for the list table
		$columns  = $this->get_columns();
		$hidden   = array();
		$sortable = $this->get_sortable_columns();
		$this->_column_headers = array( $columns, $hidden, $sortable );

		// get items
		$args = array(
			'post_type' => $this->post_type
		);
		if ( isset( $_REQUEST['s'] ) ) {
			$args['s'] = esc_attr( $_REQUEST['s'] );
		}

		$items = Theme_Posts_Helper::get_posts( $args );

		// sort
		$orderby  = isset( $_GET['orderby'] ) ? $_GET['orderby'] : 'post_date';
		$order    = isset( $_GET['order'] ) ? $_GET['order'] : 'desc';
		$callback = method_exists( __CLASS__, 'sortby_' . $orderby . '_' . $order ) ? array( __CLASS__, 'sortby_' . $orderby . '_' . $order ) : array( __CLASS__, 'sortby_date_desc' );
		usort( $items, $callback );

		// pagination
		$per_page     = $this->get_items_per_page( 'theme_posts_per_page', $this->posts_per_page );
		$current_page = $this->get_pagenum();
		$total_items  = count( $items );
		$this->set_pagination_args(
			array(
				'total_items' => $total_items,
				'per_page'    => $per_page,
			)
		);

		// debug( $items );

		// debug( Post_Export::handle_export_bulk_action( 'localhost', 'greyd_export', array_map( function( $item ) {
		// 	return $item->ID;
		// }, $items ) ) );

		// set items
		$this->items = array_slice( $items, ( $current_page - 1 ) * $per_page, $per_page );
	}


	/**
	 * =================================================================
	 *                          RENDER
	 * =================================================================
	 */

	public function render() {
		echo '<div class="wrap">';
		echo '<h1 class="wp-heading-inline">' . esc_html( get_admin_page_title() ) . '</h1>';
		echo sprintf(
			'<a href="%s" class="page-title-action">%s</a>',
			admin_url( 'site-editor.php' ),
			__( 'Site Editor', 'greyd_hub' )
		);
		echo '<hr class="wp-header-end">';

		echo '<p>' . __( 'Here you can manage all the customized content of your theme. This content is often not directly visible, but is used by your theme. For example, you have the option of exporting templates, styles, fonts, blocks and navigations and importing them into another theme.', 'greyd_hub' ) . '</p>';

		$this->tabs();

		echo '<form id="posts-filter" method="post">';

		$this->display();

		echo '</form>';
		echo '</div>';
	}

	/**
	 * Generates the table navigation above or below the table
	 *
	 * @since 3.1.0
	 * @param string $which
	 */
	protected function display_tablenav( $which ) {
		if ( 'top' === $which ) {
			wp_nonce_field( 'bulk-' . $this->_args['plural'] );
			// $this->search_box( __( 'Search' ), 'search-box-id' );
		}
		?>
		<div class="tablenav <?php echo esc_attr( $which ); ?>">

			<?php if ( $this->has_items() ) : ?>
			<div class="alignleft actions bulkactions">
				<?php $this->bulk_actions( $which ); ?>
			</div>
				<?php
			endif;
			$this->extra_tablenav( $which );
			$this->pagination( $which );
			?>

			<br class="clear" />
		</div>
		<?php
	}

	public function get_columns() {
		return array(
			'cb'         => '<input type="checkbox" />',
			'title'      => __( 'Post Title', 'greyd_hub' ),
			'post_name'  => __( 'Slug', 'greyd_hub' ),
			'post_type'  => __( 'Post Type', 'greyd_hub' ),
			'author'     => __( 'Author', 'greyd_hub' ),
			'date'       => __( 'Date', 'greyd_hub' )
		);
	}

	public function get_sortable_columns() {
		return array(
			'title'     => array( 'title', false ),
			'post_name' => array( 'post_name', false ),
			'post_type' => array( 'post_type', false ),
			'author'    => array( 'author', false ),
			'date'      => array( 'date', false ),
		);
	}

	/**
	 * Render the tabs
	 */
	public function tabs() {

		$current = is_string( $this->post_type ) ? $this->post_type : '';

		echo "<div class='greyd_tabs'>";
		echo sprintf(
			"<a href='%s' class='tab %s'>%s</a>",
			remove_query_arg( 'post_type' ),
			empty( $current ) ? 'active' : '',
			__( 'All', 'greyd_hub' )
		);
		foreach ( Theme_Posts_Helper::get_supported_post_types() as $post_type ) {
			$post_type_obj = get_post_type_object( $post_type );
			echo sprintf(
				"<a href='%s' class='tab blue %s'>%s</a>",
				add_query_arg(
					'post_type',
					'_' . $post_type, // add '_' char to argument
					remove_query_arg( array( 'paged' ) )
				),
				$current == $post_type ? 'active' : '',
				$post_type_obj ? $post_type_obj->labels->singular_name : $post_type
			);
		}
		echo '</div>';
	}

	/**
	 * Display text when no items found
	 */
	public function no_items() {

		$text = __( 'No posts found.', 'greyd_hub' );

		echo '<div style="margin: 4px 0;">' . $text . '</div>';
	}


	/**
	 * =================================================================
	 *                          COLUMNS
	 * =================================================================
	 */

	/**
	 * Handles the post title & actions column output.
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_title( $post ) {

		$edit_post_link  = Theme_Posts_Helper::get_edit_post_link( $post );
		$trash_post_link = Theme_Posts_Helper::get_delete_post_link( $post );

		$row_actions = array(
			'edit' => sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				$edit_post_link,
				/* translators: %s: Post title. */
				esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $post->post_title ) ),
				__( 'Edit', 'greyd_hub' )
			),
			'trash' => sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				$trash_post_link,
				/* translators: %s: Post title. */
				esc_attr( sprintf( __( 'Move &#8220;%s&#8221; to the Trash' ), $post->post_title ) ),
				__( 'Trash', 'greyd_hub' )
			),
			'greyd_export' => sprintf(
				'<a style="cursor:pointer;" onclick="greyd.postExport.openExport(this);" data-post_id="%s">%s</a>',
				$post->ID,
				__( 'Export', 'greyd_hub' )
			),
			'rename_template' => sprintf(
				'<a style="cursor:pointer;" onclick="greyd.postExport.openRenameTemplate(this);" data-post_id="%s" data-post_title="%s" data-post_name="%s">%s</a>',
				$post->ID,
				$post->post_title,
				$post->post_name,
				__( 'Rename', 'greyd_hub' )
			),
		);

		if ( empty( $edit_post_link ) ) {
			unset( $row_actions['edit'] );
		}
		if ( $post->post_type == 'wp_global_styles' ) {
			unset( $row_actions['rename_template'] );
		}

		$error       = '';
		$post_status = '';

		$template_theme = Theme_Posts_Helper::get_wp_template_theme( $post );
		if ( $template_theme ) {

			$template_theme_name = '';
			$theme_object        = wp_get_theme( $template_theme );

			if ( $theme_object instanceof \WP_Theme ) {
				$template_theme_name = $theme_object->get( 'Name' );
			}
	
			// check if the template is from the current theme
			if ( get_option( 'stylesheet' ) != $template_theme ) {

				$error = sprintf(
					__( 'This asset was created with a different theme (%s) and is not available for the current theme (%s).', 'greyd_hub' ),
					$template_theme_name,
					get_option( 'stylesheet' )
				);

				// add the switch theme action
				if ( $post->post_type == 'wp_template' || $post->post_type == 'wp_template_part' ) {
					$row_actions['switch_template_theme'] = sprintf(
						'<a style="cursor:pointer;" onclick="greyd.postExport.openSwitchTemplateTheme(this);" data-post_id="%s">%s</a>',
						$post->ID,
						__( 'Assign to current Theme', 'greyd_hub' )
					);
				}
				else if ( $post->post_type == 'wp_global_styles' ) {
					$row_actions['switch_global_styles'] = sprintf(
						'<a style="cursor:pointer;" onclick="greyd.postExport.openSwitchGlobalStyles(this, \''.$template_theme.'\');" data-post_id="%s">%s</a>',
						$post->ID,
						__( 'Assign to current Theme', 'greyd_hub' )
					);
				}
			}
		}

		// add the post status to the title
		if ( ! empty( $post_status ) ) {
			$post_status = ' - <span class="post-state">' . $post_status . '</span>';
		}

		// render the post title
		if ( empty( $error ) && ! empty( $edit_post_link ) ) {
			$content = sprintf(
				'<strong><a class="row-title" href="%s">%s</a>%s</strong>',
				$edit_post_link,
				$post->post_title,
				$post_status
			);
		}
		else {
			$content = sprintf(
				'<strong><span class="row-title">%s</span>%s&nbsp;%s</strong>',
				$post->post_title,
				$post_status,
				Helper::render_info_popup( $error, 'right' )
			);
		}

		// row actions
		$content .= $this->row_actions( $row_actions );

		return $content;
	}

	/**
	 * Handles the post_name column output.
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_post_name( $post ) {

		return $post->post_name;
	}

	/**
	 * Handles the post_type column output.
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_post_type( $post ) {

		$post_type_obj = get_post_type_object( $post->post_type );

		if ( $post_type_obj ) {
			return $post_type_obj->labels->singular_name;
		} else {
			return '<i>' . $post->post_type . '</i>';
		}
	}

	/**
	 * Handles the author column output.
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_author( $post ) {
		$author = get_userdata( $post->post_author );
		return $author ? $author->display_name : 'N/A';
	}

	/**
	 * Handles the post date column output.
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_date( $post ) {
		global $mode;

		if ( '0000-00-00 00:00:00' === $post->post_date ) {
			$t_time    = __( 'Unpublished' );
			$time_diff = 0;
		} else {
			$t_time = sprintf(
				/* translators: 1: Post date, 2: Post time. */
				__( '%1$s at %2$s' ),
				/* translators: Post date format. See https://www.php.net/manual/datetime.format.php */
				get_the_time( __( 'Y/m/d' ), $post ),
				/* translators: Post time format. See https://www.php.net/manual/datetime.format.php */
				get_the_time( __( 'g:i a' ), $post )
			);

			$time      = get_post_timestamp( $post );
			$time_diff = time() - $time;
		}

		if ( 'publish' === $post->post_status ) {
			$status = __( 'Published' );
		} elseif ( 'future' === $post->post_status ) {
			if ( $time_diff > 0 ) {
				$status = '<strong class="error-message">' . __( 'Missed schedule' ) . '</strong>';
			} else {
				$status = __( 'Scheduled' );
			}
		} else {
			$status = __( 'Last Modified' );
		}

		/**
		 * Filters the status text of the post.
		 *
		 * @since 4.8.0
		 *
		 * @param string  $status      The status text.
		 * @param WP_Post $post        Post object.
		 * @param string  $column_name The column name.
		 * @param string  $mode        The list display mode ('excerpt' or 'list').
		 */
		$status = apply_filters( 'post_date_column_status', $status, $post, 'date', $mode );

		if ( $status ) {
			echo $status . '<br />';
		}

		/**
		 * Filters the published, scheduled, or unpublished time of the post.
		 *
		 * @since 2.5.1
		 * @since 5.5.0 Removed the difference between 'excerpt' and 'list' modes.
		 *              The published time and date are both displayed now,
		 *              which is equivalent to the previous 'excerpt' mode.
		 *
		 * @param string  $t_time      The published time.
		 * @param WP_Post $post        Post object.
		 * @param string  $column_name The column name.
		 * @param string  $mode        The list display mode ('excerpt' or 'list').
		 */
		echo apply_filters( 'post_date_column_time', $t_time, $post, 'date', $mode );
	}


	/**
	 * =================================================================
	 *                          BULK ACTIONS
	 * =================================================================
	 */

	public function column_cb( $item ) {
		return sprintf(
			'<input type="checkbox" name="post[]" value="%s" />',
			$item->ID
		);
	}

	/**
	 * Returns an associative array containing the bulk action
	 *
	 * @return array
	 */
	public function get_bulk_actions() {
		$actions = array(
			'trash'        => __( 'Move to Trash', 'greyd_hub' ),
			'export'       => __( 'Export', 'greyd_hub' ),
			'switch_theme' => __( 'Assign to current Theme', 'greyd_hub' ),
		);
		return $actions;
	}

	/**
	 * Process the bulk actions
	 * Called via prepare_items()
	 */
	public function process_bulk_action() {

		// verify the nonce
		if (
			! isset( $_REQUEST['_wpnonce'] ) ||
			! wp_verify_nonce( $_REQUEST['_wpnonce'], 'bulk-' . $this->_args['plural'] )
		) {
			return false;
		}

		// get the action
		$bulk_action = isset( $_POST['action'] ) ? $_POST['action'] : ( isset( $_POST['action'] ) ? $_POST['action2'] : null );
		if ( empty( $bulk_action ) ) {
			return;
		}

		// get the data
		$post_ids = isset( $_POST['post'] ) ? $_POST['post'] : array();

		// normally the values are set as an array of inputs (checkboxes)
		if ( is_array( $post_ids ) ) {
			$post_ids = esc_sql( $post_ids );
		}
		// but if the user confirmed the action (eg. on 'delete'),
		// the values are set as an encoded string
		elseif ( is_string( $post_ids ) ) {
			$post_ids = esc_sql( json_decode( stripslashes( $post_ids ), true ) );
		}

		// vars used to display the admin notice
		$result         = false;
		$post_titles    = array();
		$notice_content = ''; // additional content rendered inside the admin notice
		$notice_class   = 'success'; // success admin notice type

		// perform the action...
		switch ( $bulk_action ) {

			case 'trash':
				
				foreach ( $post_ids as $post_id ) {
					$post = get_post( $post_id );
					if ( $post ) {
						$post_title = $post->post_title;
						$result     = (bool) wp_trash_post( $post_id );
						if ( $result ) {
							$post_titles[] = $post_title;
						}
					}
				}

				break;

			case 'switch_theme':
				
				foreach ( $post_ids as $post_id ) {
					$post = get_post( $post_id );
					if ( $post ) {
						$post_title = $post->post_title;
						
						if ( $post->post_type == 'wp_template' || $post->post_type == 'wp_template_part') {
							$result = Theme_Posts_Helper::set_wp_template_theme( $post, true );
						}
						else if ( $post->post_type == 'wp_global_styles' ) {
							$result = Theme_Posts_Helper::set_wp_global_styles_theme( $post );
						}
						else {
							$result = false;
						}

						if ( $result ) {
							$post_titles[] = $post_title;
						}
					}
				}

				break;

			case 'export':
				
				$zip_uri = Post_Export::handle_export_bulk_action( '', 'greyd_export', $post_ids );

				$unique_id = uniqid( 'greyd_export_download_' );
				echo '<a id="' . $unique_id . '" href="' . $zip_uri . '" download style="display:none;"></a>';
				echo '<script>document.getElementById("' . $unique_id . '").click();</script>';
				
				break;

			default:
				break;
		}

		// set the admin notice content
		$notices = array(
			'edit'             => array(
				'success' => __( 'The posts %s have been successfully edited.', 'greyd_hub' ),
				'fail'    => __( 'There were errors when editing the posts.', 'greyd_hub' ),
			),
			'trash'            => array(
				'success' => __( 'The posts %s have been successfully moved to the trash.', 'greyd_hub' ),
				'fail'    => __( 'Errors occurred when moving posts to the trash.', 'greyd_hub' ),
			),
			'switch_theme'     => array(
				'success' => __( 'The posts %s have been successfully assigned to the current theme', 'greyd_hub' ),
				'fail'    => __( 'Errors occurred when assigning posts to the current theme.', 'greyd_hub' ),
			),
			'export'           => array(
				'success' => __( 'The posts %s were exported successfully.', 'greyd_hub' ),
				'fail'    => __( 'Errors occurred when exporting the posts.', 'greyd_hub' ),
			),
		);

		// display the admin notice
		if ( $result === true ) {
			if ( count( $post_titles ) > 1 ) {
				$last        = array_pop( $post_titles );
				$post_titles = implode( ', ', $post_titles ) . ' & ' . $last;
			} else {
				$post_titles = implode( ', ', $post_titles );
			}
			$content = sprintf( $notices[ $bulk_action ]['success'], "<strong>$post_titles</strong>" );
		} else {
			$notice_class = 'error';
			$content      = $notices[ $bulk_action ]['fail'];
			if ( is_string( $result ) && ! empty( $result ) ) {
				$content .= ' ' . __( 'Error message:', 'greyd_hub' ) . ' ' . $result;
			}
		}

		// display the admin notice
		Helper::show_message( $content . $notice_content, $notice_class );
	}


	/**
	 * =================================================================
	 *                          SORT CALLBACKS
	 * =================================================================
	 */

	public function sort_alphabet( $a, $b ) {
		return strcasecmp( $b, $a );
	}
	// post_date
	public function sortby_date_asc( $a, $b ) {
		return strtotime( $a->post_date ) - strtotime( $b->post_date );
	}
	public function sortby_date_desc( $a, $b ) {
		return -1 * $this->sortby_post_date_asc( $a, $b );
	}
	// post_title
	public function sortby_title_asc( $a, $b ) {
		return $this->sort_alphabet( $a->post_title, $b->post_title );
	}
	public function sortby_title_desc( $a, $b ) {
		return -1 * $this->sortby_post_title_asc( $a, $b );
	}
	// post_name
	public function sortby_post_name_asc( $a, $b ) {
		return $this->sort_alphabet( $a->post_name, $b->post_name );
	}
	public function sortby_post_name_desc( $a, $b ) {
		return -1 * $this->sortby_post_name_asc( $a, $b );
	}
	// post_type
	public function sortby_post_type_asc( $a, $b ) {
		$a_post_type = post_type_exists( $a->post_type ) ? get_post_type_object( $a->post_type )->labels->singular_name : $a->post_type;
		$b_post_type = post_type_exists( $b->post_type ) ? get_post_type_object( $b->post_type )->labels->singular_name : $b->post_type;
		return $this->sort_alphabet( $a_post_type, $b_post_type );
	}
	public function sortby_post_type_desc( $a, $b ) {
		return -1 * $this->sortby_post_type_asc( $a, $b );
	}
	// author
	public function sortby_author_asc( $a, $b ) {
		// compare author IDs numerically
		$a_author_id = $a->post_author;
		$b_author_id = $b->post_author;
		if ( $a_author_id != $b_author_id ) {
			return $a_author_id - $b_author_id;
		}
	}
	public function sortby_author_desc( $a, $b ) {
		return -1 * $this->sortby_author_asc( $a, $b );
	}
}
