<?php
namespace SabaiApps\Directories\Component\Dashboard\Panel;

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Entity\Model\Bundle;
use SabaiApps\Directories\Exception;
use SabaiApps\Framework\User\AbstractIdentity;
use SabaiApps\Directories\Component\Display\Controller\Admin\AddDisplay;

class PostsPanel extends AbstractPanel {

	protected $_bundleGroup;

	public function __construct( Application $application, $name ) {
		parent::__construct( $application, $name );
		$this->_bundleGroup = substr( $name, strlen( 'posts_' ) );
	}

	protected function _dashboardPanelInfo() {
		return array(
			'weight'           => 1,
			'labellable'       => false,
			'default_settings' => array(
				'add_post_btn'   => true,
				'add_show_label' => false,
				'show_others'    => false,
				'no_ajax'        => true,
				'hide_empty'     => false,
			),
			'public'           => true,
			'guest_allowed'    => true,
		);
	}

	public function dashboardPanelOnLoad( $isPublic = false ) {
		if ( $this->_application->getPlatform()->isAdmin() ) {
			return;
		}

		$this->_application->getPlatform()->loadJqueryUiJs( array( 'effects-highlight' ) );
	}

	public function dashboardPanelLabel() {
		if ( $directory = $this->_application->getModel( 'Directory', 'Directory' )->name_is( $this->_bundleGroup )->fetchOne() ) {
			return $directory->getLabel();
		}
	}

	protected function _dashboardPanelLinks( array $settings, ?AbstractIdentity $identity = null ) {
		if ( ! $bundles = $this->_application->Entity_Bundles( null, $this->_bundleGroup ) ) {
			return;
		}

		if ( $this->_application->getUser()->isAnonymous()
			&& ( ! $guest_email = $this->_application->Dashboard_GuestAccess_isGranted() )
		) {
			return; // this should not happen if already made this far
		}

		$ret         = array();
		$weight      = 0;
		$entity_type = null;
		foreach ( $bundles as $bundle ) {
			if ( ! $this->_isBundlePanelEnabled( $bundle, $settings, $identity ) ) {
				continue;
			}

			++$weight;
			$ret[ $bundle->name ] = array(
				'title'   => $bundle->getLabel(),
				'weight'  => empty( $bundle->info['parent'] ) && empty( $bundle->info['parent_field'] ) ? $weight : 100 + $weight,
				'icon'    => $this->_application->Entity_BundleTypeInfo( $bundle, 'icon' ),
				'no_ajax' => false, // !empty($settings['no_ajax']),
			);
			$entity_type          = $bundle->entitytype_name;
		}

		$show_others = false;
		if ( $user_id = isset( $identity ) ? $identity->id : $this->_application->getUser()->id ) {
			$language = $this->_application->getPlatform()->getCurrentLanguage();
			$cache_id = 'dashboard_post_counts_' . $this->_bundleGroup . '_' . $user_id . '_' . $language;
			if ( ! isset( $identity )
				&& ( $show_others = ! empty( $settings['show_others'] ) )
			) {
				$cache_id .= '_o' . (int) $show_others;
			}
		}

		if ( ! isset( $cache_id )
			|| ( ! $counts = $this->_application->getPlatform()->getCache( $cache_id, 'content' ) )
		) {
			$counts = array();
			if ( ! empty( $ret ) ) {
				$statuses          = array();
				$valid_status_keys = isset( $identity ) ? array( 'publish' ) : array( 'publish', 'pending', 'draft', 'private' );
				foreach ( $valid_status_keys as $status_key ) {
					$statuses[ $status_key ] = $this->_application->Entity_Status( $entity_type, $status_key );
				}

				foreach ( array_keys( $ret ) as $bundle_name ) {
					if ( $show_others
						&& ( $this->_application->HasPermission( 'entity_edit_others_' . $bundle_name )
							|| $this->_application->HasPermission( 'entity_delete_others_' . $bundle_name ) )
					) {
						$other_statuses = $statuses;
						if ( ! $this->_application->HasPermission( 'entity_edit_published_' . $bundle_name )
							&& ! $this->_application->HasPermission( 'entity_delete_published_' . $bundle_name )
						) {
							unset( $other_statuses['publish'] );
						}
						if ( ! $this->_application->HasPermission( 'entity_edit_private_' . $bundle_name )
							&& ! $this->_application->HasPermission( 'entity_delete_private_' . $bundle_name )
						) {
							unset( $other_statuses['private'] );
						}
						$counts[ $bundle_name ] = $this->_application->Entity_Query( $entity_type, $bundle_name )
							->startCriteriaGroup( 'OR' )
								->startCriteriaGroup( 'AND' )
									->fieldIsIn( 'status', $statuses )
									->fieldIs( 'author', $user_id )
								->finishCriteriaGroup()
								->startCriteriaGroup( 'AND' )
									->fieldIsIn( 'status', $other_statuses )
									->fieldIsNot( 'author', $user_id )
								->finishCriteriaGroup()
							->finishCriteriaGroup()
							->count();
					} else {
						$query = $this->_application->Entity_Query( $entity_type, $bundle_name )
							->fieldIsIn( 'status', $statuses );
						if ( $user_id ) {
							$query->fieldIs( 'author', $user_id );
						} else {
							if ( empty( $guest_email ) ) {
								return;
							}

							$query->fieldIs( 'frontendsubmit_guest', $guest_email, 'email' );
						}
						$counts[ $bundle_name ] = $query->count();
					}
				}
			}
			if ( isset( $cache_id ) ) {
				$this->_application->getPlatform()->setCache( $counts, $cache_id, 3600, 'content' ); // cache 1 hour
			}
		}
		$is_empty = true;
		foreach ( array_keys( $ret ) as $bundle_name ) {
			if ( empty( $counts[ $bundle_name ] ) ) {
				// No posts, hide if child bundle, public profile, or no permission to create posts for the bundle
				if ( ! empty( $bundles[ $bundle_name ]->info['parent'] )
					|| ! empty( $bundles[ $bundle_name ]->info['parent_field'] )
					|| isset( $identity )
					|| ! $this->_application->HasPermission( 'entity_create_' . $bundle_name )
				) {
					unset( $ret[ $bundle_name ] );
				}
			} else {
				$ret[ $bundle_name ]['count'] = $counts[ $bundle_name ];
				$is_empty                     = false;
			}
		}
		if ( $is_empty
			&& ! empty( $settings['hide_empty'] )
		) {
			return array();
		}

		return $ret;
	}

	public function dashboardPanelContent( $link, array $settings, array $params, ?AbstractIdentity $identity = null ) {
		if ( ! $bundle = $this->_application->Entity_Bundle( $link ) ) {
			throw new Exception\RuntimeException( 'Invalid bundle: ' . $link );
		}

		if ( ! $this->_isBundlePanelEnabled( $bundle, $settings, $identity ) ) {
			return;
		}

		$_settings = array(
			'filter'     => array(
				'show'       => ! empty( $settings[ 'filter_show_' . $bundle->name ] ),
				'show_modal' => ! empty( $settings[ 'filter_show_modal_' . $bundle->name ] ),
				'display'    => empty( $settings[ 'filter_display_' . $bundle->name ] ) ? null : $settings[ 'filter_display_' . $bundle->name ],
			),
			'pagination' => array(
				'perpage'       => 20,
				'allow_perpage' => true,
				'perpages'      => array( 20, 30, 50 ),
			),
			'query'      => array(
				'user_id' => isset( $identity ) ? $identity->id : null,
			),
		);
		$sorts     = isset( $settings[ 'sorts_' . $bundle->name ] ) ? $settings[ 'sorts_' . $bundle->name ] : $this->_getDefaultSortOptions( $bundle );
		if ( ! empty( $sorts ) ) {
			$_settings['sort'] = array(
				'default' => current( array_keys( $sorts ) ),
				'options' => $sorts,
			);
		}
		if ( isset( $settings[ 'other_' . $bundle->name ] ) ) {
			$_settings['other'] = $settings[ 'other_' . $bundle->name ];
		} else {
			$_settings['other'] = array(
				'add' => array(
					'show'       => empty( $bundle->info['parent'] ) && ( ! isset( $settings['add_post_btn'] ) || $settings['add_post_btn'] ),
					'show_label' => ! empty( $settings['add_show_label'] ),
				),
				'num' => true,
			);
		}
		if ( ! empty( $bundle->info['public'] ) ) {
			if ( ! isset( $identity ) ) {
				$_settings['query']['status'] = array( 'publish', 'pending', 'draft', 'private' );

				if ( ! empty( $settings['show_others'] ) ) {
					// Set statuses for other user posts if permitted
					if ( $this->_application->HasPermission( 'entity_edit_others_' . $bundle->name )
						|| $this->_application->HasPermission( 'entity_delete_others_' . $bundle->name )
					) {
						$status_others = array( 'pending', 'draft' );
						if ( $this->_application->HasPermission( 'entity_edit_published_' . $bundle->name )
							|| $this->_application->HasPermission( 'entity_delete_published_' . $bundle->name )
						) {
							$status_others[] = 'publish';
						}
						if ( $this->_application->HasPermission( 'entity_edit_private_' . $bundle->name )
							|| $this->_application->HasPermission( 'entity_delete_private_' . $bundle->name )
						) {
							$status_others[] = 'private';
						}
						$_settings['query']['status_others'] = $status_others;
					}
				}
			}
		}
		if ( ! isset( $identity )
			&& $this->_application->getUser()->isAnonymous()
		) {
			if ( ! $guest_email = $this->_application->Dashboard_GuestAccess_isGranted() ) {
				return;
			}

			$_settings['query']['fields']['frontendsubmit_guest'] = $guest_email;
		}

		// Let other components modify settings
		$_settings = $this->_application->Filter( 'dashboard_posts_panel_view_settings', $_settings, array( $bundle, $identity ) );

		return $this->_application->getPlatform()->render(
			$bundle->getPath(),
			array(
				'settings' => array(
					'mode'          => 'dashboard_dashboard',
					'view_settings' => $_settings,
					'no_json'       => true,
				),
			)
		);
	}

	protected function _isBundlePanelEnabled( Bundle $bundle, array $settings, ?AbstractIdentity $identity = null ) {
		return $bundle->entitytype_name === 'post'
			&& ( ! isset( $identity ) || ! empty( $bundle->info['public'] ) )
			&& ( ! isset( $settings[ 'enable_' . $bundle->name ] ) || ! empty( $settings[ 'enable_' . $bundle->name ] ) )
			&& ! $this->_application->Entity_BundleTypeInfo( $bundle->type, 'dashboard_disable' );
	}

	protected function _getDefaultSortOptions( Bundle $bundle ) {
		if ( empty( $bundle->info['public'] ) ) {
			$sorts = array(
				$bundle->entitytype_name . '_published',
				$bundle->entitytype_name . '_published,asc',
			);
		} else {
			$sorts = array(
				$bundle->entitytype_name . '_published',
				$bundle->entitytype_name . '_title',
				$bundle->entitytype_name . '_published,asc',
				empty( $bundle->info['review_enable'] ) ? 'voting_rating' : 'review_ratings',
				'voting_bookmark',
				'voting_updown',
			);
		}
		return $this->_application->Filter( 'dashboard_posts_panel_default_sorts', $sorts, array( $bundle ) );
	}

	public function dashboardPanelSettingsForm( array $settings, array $parents ) {
		$form = array();
		if ( $bundles = $this->_application->Entity_Bundles( null, $this->_bundleGroup ) ) {
			$_weight = 10;
			foreach ( $bundles as $bundle ) {
				if ( $bundle->entitytype_name !== 'post'
					|| $this->_application->Entity_BundleTypeInfo( $bundle->type, 'dashboard_disable' )
				) {
					continue;
				}

				if ( ! empty( $bundle->info['is_primary'] ) ) {
					$title_prefix = '';
					$weight       = 1;
				} else {
					$title_prefix = $bundle->getLabel() . ' - ';
					$weight       = ++$_weight;
				}

				$states = array();
				if ( ! empty( $bundle->info['parent'] )
					|| ! empty( $bundle->info['parent_field'] )
				) {
					$enable_key          = 'enable_' . $bundle->name;
					$form[ $enable_key ] = array(
						'#type'          => 'checkbox',
						'#title'         => $title_prefix . __( 'Enable panel', 'directories-pro' ),
						'#horizontal'    => true,
						'#default_value' => ! isset( $settings[ $enable_key ] ) || ! empty( $settings[ $enable_key ] ),
						'#weight'        => $weight,
					);
					$states['visible'][ sprintf( '[name="%s"]', $this->_application->Form_Form_fieldName( array_merge( $parents, array( $enable_key ) ) ) ) ] = array(
						'type'  => 'checked',
						'value' => true,
					);
				}

				if ( $this->_application->getComponent( 'View' )->isFilterable( $bundle )
					&& ( $displays = AddDisplay::existingDisplays( $this->_application, $bundle->name, 'default', 'filters' ) )
				) {
					$show_key                = 'filter_show_' . $bundle->name;
					$show_selector           = sprintf( '[name="%s"]', $this->_application->Form_Form_fieldName( array_merge( $parents, array( $show_key ) ) ) );
					$form[ $show_key ]       = array(
						'#type'          => 'checkbox',
						'#title'         => $title_prefix . __( 'Show filter form', 'directories-pro' ),
						'#horizontal'    => true,
						'#default_value' => ! empty( $settings[ $show_key ] ),
						'#weight'        => $weight,
						'#states'        => $states,
					);
					$show_modal_key          = 'filter_show_modal_' . $bundle->name;
					$form[ $show_modal_key ] = array(
						'#type'          => 'checkbox',
						'#title'         => $title_prefix . __( 'Show filter form in modal window', 'directories-pro' ),
						'#default_value' => ! empty( $settings[ $show_modal_key ] ),
						'#horizontal'    => true,
						'#weight'        => $weight,
						'#states'        => array(
							'visible' => isset( $states['visible'] )
								? $states['visible'] + array(
									$show_selector => array(
										'type'  => 'checked',
										'value' => true,
									),
								)
								: array(
									$show_selector => array(
										'type'  => 'checked',
										'value' => true,
									),
								),
						),
					);
					$display_key             = 'filter_display_' . $bundle->name;
					if ( count( $displays ) > 1 ) {
						$form[ $display_key ] = array(
							'#type'          => 'select',
							'#title'         => $title_prefix . __( 'Select filter group', 'directories-pro' ),
							'#options'       => $displays,
							'#horizontal'    => true,
							'#default_value' => isset( $settings[ $display_key ] ) && isset( $displays[ $settings[ $display_key ] ] ) ? $settings[ $display_key ] : null,
							'#weight'        => $weight,
							'#states'        => array(
								'visible' => isset( $states['visible'] )
									? $states['visible'] + array(
										$show_selector => array(
											'type'  => 'checked',
											'value' => true,
										),
									)
									: array(
										$show_selector => array(
											'type'  => 'checked',
											'value' => true,
										),
									),
							),
						);
					} else {
						$form[ $display_key ] = array(
							'#type'          => 'hidden',
							'#default_value' => '',
						);
					}
				}

				$sorts_key          = 'sorts_' . $bundle->name;
				$form[ $sorts_key ] = array(
					'#type'             => 'sortablecheckboxes',
					'#options'          => $this->_application->Entity_Sorts_options( $bundle, true ),
					'#option_no_escape' => true,
					'#default_value'    => isset( $settings[ $sorts_key ] ) ? $settings[ $sorts_key ] : $this->_getDefaultSortOptions( $bundle ),
					'#title'            => $title_prefix . __( 'Sort options', 'directories-pro' ),
					'#horizontal'       => true,
					'#weight'           => $weight,
					'#states'           => $states,
				);
				if ( ! empty( $bundle->info['is_primary'] ) ) {
					$other_key          = 'other_' . $bundle->name;
					$other_settings     = isset( $settings[ $other_key ] ) ? $settings[ $other_key ] : array();
					$form[ $other_key ] = array(
						'#weight'     => $weight,
						'#horizontal' => true,
					) + $this->_application->View_SettingsForm_feature( $bundle, 'other', $other_settings, false, $title_prefix, array_merge( $parents, array( $other_key ) ) );
				}
			}
		}
		$form += array(
			'show_others' => array(
				'#type'          => 'checkbox',
				'#title'         => __( "Include other user's posts", 'directories-pro' ),
				'#horizontal'    => true,
				'#default_value' => ! empty( $settings['show_others'] ),
				'#weight'        => 5,
			),
			'no_ajax'     => array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Disable loading panel content using AJAX', 'directories-pro' ),
				'#horizontal'    => true,
				'#default_value' => ! empty( $settings['no_ajax'] ),
				'#weight'        => 6,
			),
			'hide_empty'  => array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Hide panel when empty', 'directories-pro' ),
				'#horizontal'    => true,
				'#default_value' => ! empty( $settings['hide_empty'] ),
				'#weight'        => 6,
			),
		);

		return $form;
	}
}
