<?php
namespace SabaiApps\Directories\Component\Voting\DisplayButton;

use SabaiApps\Directories\Component\Display\Button\AbstractButton;
use SabaiApps\Directories\Application;
use SabaiApps\Directories\Request;
use SabaiApps\Directories\Component\Entity\Model\Bundle;
use SabaiApps\Directories\Component\Entity\Type\IEntity;

class VoteDisplayButton extends AbstractButton {

	protected $_type, $_downVote = false;

	public function __construct( Application $application, $name ) {
		parent::__construct( $application, $name );
		if ( substr( $this->_name, -5 ) === '_down' ) {
			$this->_downVote = true;
			$this->_type     = substr( $this->_name, 7, -5 ); // remove voting_ prefix and _down suffix
		} else {
			$this->_type = substr( $this->_name, 7 ); // remove voting_ prefix
		}
	}

	protected function _displayButtonInfo( Bundle $bundle ) {
		$info      = $this->_application->Voting_Types_impl( $this->_type )->votingTypeInfo();
		$color_key = $this->_downVote ? 'color_down' : 'color';
		return array(
			'label'            => $this->_downVote ? $info['label_button_down'] : $info['label_button'],
			'default_settings' => array(
				'_color'     => isset( $info[ $color_key ] ) ? $info[ $color_key ] : 'outline-secondary',
				'show_count' => false,
				'_icon'      => $this->_downVote ? $info['icon_down'] : $info['icon'], // required for overlay button
			),
			'labellable'       => false,
			'iconable'         => false,
		);
	}

	public function displayButtonSettingsForm( Bundle $bundle, array $settings, $displayName, array $parents = array() ) {
		return array(
			'show_count' => array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Show count', 'directories-pro' ),
				'#default_value' => ! empty( $settings['show_count'] ),
				'#horizontal'    => true,
				'#states'        => array(
					'visible' => array(
						sprintf( '[name="%s[_hide_label]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
							'type'  => 'checked',
							'value' => false,
						),
					),
				),
				'#weight'        => 1,
			),
		) + $this->_application->Voting_Types_impl( $this->_type )->votingTypeButtonSettingsForm( $bundle, $settings, $parents );
	}

	public function displayButtonLink( Bundle $bundle, IEntity $entity, array $settings, $displayName ) {
		$type_impl = $this->_application->Voting_Types_impl( $this->_type );
		if ( ! $type_impl->votingTypeIsEnabled() ) {
			return;
		}

		$class     = $settings['_class'] . ' drts-voting-button';
		$type_info = $type_impl->votingTypeInfo();
		if ( $this->_downVote ) {
			$label_action   = sprintf( $type_info['label_btn_down'] ?? $type_info['label_action_down'], $bundle->getLabel( 'singular' ) );
			$label_unaction = sprintf( $type_info['label_unaction_down'], $bundle->getLabel( 'singular' ) );
			$icon           = $type_info['icon_down'];
			$active_icon    = isset( $type_info['icon_down_active'] ) ? $type_info['icon_down_active'] : $icon;
		} else {
			$label_action   = sprintf( $type_info['label_btn'] ?? $type_info['label_action'], $bundle->getLabel( 'singular' ) );
			$label_unaction = sprintf( $type_info['label_unaction'], $bundle->getLabel( 'singular' ) );
			$icon           = $type_info['icon'];
			$active_icon    = isset( $type_info['icon_active'] ) ? $type_info['icon_active'] : $icon;
		}

		if ( ! $this->_application->Voting_CanVote( $entity, $this->_type, $this->_downVote ) ) {
			if ( ! $this->_application->getUser()->isAnonymous() ) {
				return;
			}

			return $this->_getLoginButton(
				$this->_getLabelHtml( $entity, $settings, $label_action ),
				$this->_getVoteUrl( $bundle, $entity ),
				array(
					'no_escape'     => true,
					'icon'          => $icon,
					'no_wrap_label' => true,
				),
				array(
					'class' => $settings['_class'],
					'style' => $settings['_style'],
				)
			);
		}

		if ( $this->_application->getUser()->isAnonymous()
			&& ! empty( $type_info['anonymous_use_cookie'] )
		) {
			$link = $this->_application->LinkTo(
				$this->_getLabelHtml( $entity, $settings, $label_action ),
				'',
				array(
					'icon'          => $icon,
					'no_escape'     => true,
					'btn'           => true,
					'no_wrap_label' => true,
				),
				array(
					'class'                   => $class,
					'style'                   => $settings['_style'],
					'rel'                     => 'nofollow',
					'data-label'              => $label_action,
					'data-label-active'       => $label_unaction,
					'data-voting-type'        => $this->_type,
					'data-voting-icon-active' => $active_icon,
					'data-voting-icon'        => $icon,
					'data-voting-guest'       => 1,
					'data-entity-id'          => $entity->getId(),
					'data-entity-type'        => $entity->getType(),
				)
			);
		} else {
			$active = false;
			$value  = $this->_downVote ? -1 : 1;
			if ( ( null !== $current_value = $this->_application->Voting_Votes( $entity->getId(), $this->_type ) )
				&& intval( $current_value ) === $value
			) {
				$active = true;
				$class .= ' ' . DRTS_BS_PREFIX . 'active';
			}
			$link = $this->_application->LinkTo(
				$this->_getLabelHtml( $entity, $settings, $active ? $label_unaction : $label_action ),
				'',
				array(
					'container'     => '',
					'icon'          => $active ? $active_icon : $icon,
					'url'           => $this->_getAjaxVoteUrl( $entity ),
					'post'          => true,
					'loadingImage'  => false,
					'sendData'      => 'DRTS.Voting.onSendData("' . $this->_type . '", trigger, data);',
					'success'       => 'DRTS.Voting.onSuccess("' . $this->_type . '", trigger, result);',
					'error'         => 'DRTS.Voting.onError("' . $this->_type . '", trigger, error);',
					'no_escape'     => true,
					'btn'           => true,
					'no_wrap_label' => true,
				),
				array(
					'class'                   => $class,
					'style'                   => $settings['_style'],
					'rel'                     => 'nofollow',
					'data-success-label'      => $active ? $label_action : $label_unaction,
					'data-active-value'       => $this->_downVote ? -1 : 1,
					'data-voting-type'        => $this->_type,
					'data-voting-icon-active' => $active_icon,
					'data-voting-icon'        => $icon,
				)
			);
		}

		$this->_application->Voting_Types_impl( $this->_type )->votingTypeOnVoteButtonLink( $link, $entity, $settings, $displayName );

		return $link;
	}

	protected function _getVoteUrl( Bundle $bundle, IEntity $entity ) {
		return $this->_application->Url(
			$bundle->getPath( false ) . '/vote',
			array(
				'entity_id'   => $entity->getId(),
				'voting_type' => $this->_type,
			)
		);
	}

	protected function _getAjaxVoteUrl( IEntity $entity, $withToken = true ) {
		$params = array( 'value' => $this->_downVote ? -1 : 1 );
		if ( $withToken ) {
			$params[ Request::PARAM_TOKEN ] = $this->_application->Form_Form_createToken( 'voting_vote_entity', 1800, true );
		}
		return $this->_application->Url(
			'/_drts/voting/vote',
			array(
				'entity_type' => $entity->getType(),
				'entity_id'   => $entity->getId(),
				'voting_type' => $this->_type,
			) + $params
		);
	}

	protected function _getLabelHtml( IEntity $entity, array $settings, $label ) {
		$html = '<span class="drts-voting-vote-label">' . $this->_application->H( $label ) . '</span>';
		if ( ! empty( $settings['show_count'] ) ) {
			if ( $val = $entity->getSingleFieldValue( 'voting_' . $this->_type, '' ) ) {
				$num = $this->_application->Voting_Types_impl( $this->_type )->votingTypeFormat( $val, $this->_downVote ? 'num_down' : 'num' );
			} else {
				$num = 0;
			}
			$margin_x_class = DRTS_BS_PREFIX . 'ms-2';
			$html          .= '<span class="drts-voting-vote-num ' . $margin_x_class . '">' . $num . '</span>';
		}
		return $html;
	}

	public function displayButtonIsPreRenderable( Bundle $bundle, array $settings ) {
		return true;
	}

	public function displayButtonPreRender( Bundle $bundle, array $settings, array $entities = array() ) {
		$this->_application->getPlatform()
			->addJsFile( 'voting.min.js', 'drts-voting', array( 'drts' ), 'directories-pro' );
		if ( ! empty( $entities ) ) {
			$this->_application->Voting_Votes_load( $bundle->name, array_keys( $entities ) );
		}
	}
}
