<?php
/**
 * My Account — address book page.
 *
 * @package Vanquish\MultipleAddresses\Frontend
 */

namespace Vanquish\MultipleAddresses\Frontend;

use Vanquish\MultipleAddresses\Com\Access;
use Vanquish\MultipleAddresses\Com\AddressForm;
use Vanquish\MultipleAddresses\Com\Addresses;
use Vanquish\MultipleAddresses\Com\Settings;
use Vanquish\MultipleAddresses\Com\Template;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Adds an "Address book" tab to the WooCommerce My Account area where customers
 * list, add, edit and delete their saved addresses, and choose which one is used
 * by default for billing and for shipping. This is the free core.
 *
 * It uses its own account endpoint rather than squeezing into WooCommerce's
 * "Addresses" screen: that screen has no usable extension hook for a list UI,
 * and an own endpoint keeps the markup fully under our control (and out of
 * other plugins' way).
 *
 * The CRUD itself is handled by AddressAjax, which the checkout selector shares.
 */
class MyAccountPage {

	/**
	 * My Account endpoint slug.
	 */
	const ENDPOINT = 'address-book';

	/**
	 * Option flag set on activation so the rewrite rules are flushed once.
	 */
	const FLUSH_FLAG = 'vanmuad_flush_rewrite';

	/**
	 * Address book service.
	 *
	 * @var Addresses
	 */
	private $addresses;

	/**
	 * Settings service.
	 *
	 * @var Settings
	 */
	private $settings;

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->addresses = new Addresses();
		$this->settings  = new Settings();

		add_action( 'init', array( $this, 'add_endpoint' ) );
		add_filter( 'query_vars', array( $this, 'add_query_var' ), 0 );
		add_filter( 'woocommerce_account_menu_items', array( $this, 'add_menu_item' ) );
		add_action( 'woocommerce_account_' . self::ENDPOINT . '_endpoint', array( $this, 'render' ) );
	}

	/**
	 * Whether the address book is available at all.
	 *
	 * The two settings switch the selector on each checkout form; turning both
	 * off means the feature is not in use, so the account tab goes too.
	 *
	 * @return bool
	 */
	public function is_enabled() {
		$switched_on = $this->settings->is_enabled( 'selector_on_billing', true )
			|| $this->settings->is_enabled( 'selector_on_shipping', true );

		return $switched_on && Access::can_use();
	}

	// -----------------------------------------------------------------------
	// Endpoint plumbing
	// -----------------------------------------------------------------------

	/**
	 * Register the account endpoint, flushing the rewrite rules once after
	 * activation so the new URL resolves without a manual permalink save.
	 *
	 * @return void
	 */
	public function add_endpoint() {
		add_rewrite_endpoint( self::ENDPOINT, EP_ROOT | EP_PAGES );

		if ( get_option( self::FLUSH_FLAG ) ) {
			delete_option( self::FLUSH_FLAG );
			flush_rewrite_rules();
		}
	}

	/**
	 * Make the endpoint a recognised query var.
	 *
	 * @param array $vars Query vars.
	 * @return array
	 */
	public function add_query_var( $vars ) {
		$vars[] = self::ENDPOINT;

		return $vars;
	}

	/**
	 * Add the tab to the My Account navigation, right after "Addresses".
	 *
	 * @param array $items Menu items.
	 * @return array
	 */
	public function add_menu_item( $items ) {
		if ( ! $this->is_enabled() ) {
			return $items;
		}

		$new   = array();
		$label = __( 'Address book', 'vanquish-multiple-addresses-for-woocommerce' );

		foreach ( $items as $key => $value ) {
			$new[ $key ] = $value;

			if ( 'edit-address' === $key ) {
				$new[ self::ENDPOINT ] = $label;
			}
		}

		// Fall back to appending it when the Addresses tab is not present.
		if ( ! isset( $new[ self::ENDPOINT ] ) ) {
			$new[ self::ENDPOINT ] = $label;
		}

		return $new;
	}

	// -----------------------------------------------------------------------
	// Rendering
	// -----------------------------------------------------------------------

	/**
	 * Render the address book.
	 *
	 * @return void
	 */
	public function render() {
		if ( ! is_user_logged_in() || ! Access::can_use() ) {
			return;
		}

		Template::render(
			'my-account/address-book.php',
			array(
				'addresses' => $this->addresses->all( get_current_user_id() ),
				'fields'    => AddressForm::fields(),
			)
		);
	}
}
