<?php

/**
 * Implements logic for multiple shops existing in one marketplace
 *
 * Every shop has its owner (organization that is commercial lead) and multiple customers (organizations)
 * assigned to it.
 *
 * Class Wiaas_Shop
 */
class Wiaas_Shop {

	public static function init() {

		// registers special prices taxonomy that will enable package search based on
		// set and visible price types (default and customer specific ones)
		add_action('woocommerce_after_register_taxonomy', array(__CLASS__, 'register_prices_taxonomy'));

		// update prices search terms for package after prices extras have been updated
		add_action('wiaas_package_prices_extras_set', array(__CLASS__, 'update_package_prices_search_terms'), 10, 4);

		// create new shop if organization was assigned commercial lead role
		// or remove shop if commercial lead role was removed for organization
		add_action('wiaas_organization_roles_updated', array(__CLASS__, 'maybe_manage_shop_for_commercial_lead'), 10, 2);

		add_action('wiaas_organization_deleted', array(__CLASS__, 'maybe_remove_shop'));
	}

	public static function get_shop_customers($owner_id) {
		return Wiaas_Shop_DB::get_shop_customers($owner_id);
	}

	/**
	 * Link customers to shop (this will enable them to search and order packages from this shop)
	 *
	 * @param int $owner_id
	 * @param array $customer_ids
	 */
	public static function set_shop_customers($owner_id, $customer_ids) {

		$current_customer_ids = wp_list_pluck(
			Wiaas_Shop_DB::get_shop_customers($owner_id),
			'customer_id');

		// delete removed customers
		$removed_customer_ids = array_diff($current_customer_ids, $customer_ids);
		Wiaas_Shop_DB::remove_shop_customers($owner_id, $removed_customer_ids);

		// save added customers
		$added_customer_ids = array_diff($customer_ids, $current_customer_ids);
		Wiaas_Shop_DB::add_shop_customers($owner_id, $added_customer_ids);
	}

	/**
	 * Retrieve default order type for shop
	 *
	 * @param int $owner_id
	 *
	 * @return string
	 */
	public static function get_default_order_type($owner_id) {
		$order_type = get_term_meta(
			$owner_id,
			'_wiaas_shop_default_order_type',
			true);

		return empty($order_type) ? 'commercial_lead' : $order_type;
	}

	/**
	 * Update default order type for shop
	 *
	 * @param int $owner_id
	 * @param string $order_type
	 */
	public static function update_default_order_type($owner_id, $order_type) {

		if (in_array($order_type, array('commercial_lead', 'reseller'))) {
			update_term_meta($owner_id,  '_wiaas_shop_default_order_type', $order_type);
		}
	}

	public static function update_shop_customer_order_type($owner_id, $customer_id, $order_type) {
		Wiaas_Shop_DB::update_shop_customer_order_type(
			$owner_id,
			$customer_id,
			$order_type);
	}

	/**
	 * Creates shop for new shop owner (organization with commercial lead role) or
	 * deletes existing shop if that role has been removed
	 *
	 * @param int $owner_id
	 * @param array $roles
	 */
	public static function maybe_manage_shop_for_commercial_lead($owner_id, $roles) {
		$is_commercial_lead = in_array('commercial_lead', $roles);

		$is_commercial_lead ?
			self::_maybe_create_shop($owner_id) :
			self::_maybe_remove_shop($owner_id);
	}

	/**
	 * Remove shop
	 *
	 * @param int $owner_id
	 */
	public static function maybe_remove_shop($owner_id) {
		self::_maybe_remove_shop($owner_id);
	}

	/**
	 * Register special prices taxonomy to enable search of packages by prices inside every shop
	 */
	public static function register_prices_taxonomy() {
		$args = array(
			'hierarchical'      => false,
			'query_var'         => true,
			'rewrite'           => false,
			'public'            => false,
			'capabilities'          => array(
				'manage_terms' => 'manage_wiaas_package_price_terms',
				'edit_terms'   => 'edit_wiaas_package_price_terms',
				'delete_terms' => 'delete_wiaas_package_price_terms',
				'assign_terms' => 'assign_wiaas_package_price_terms',
			),
		);

		register_taxonomy( '_wiaas_shop_prices', array( 'product' ), $args );
	}

	/**
	 * Relate pricing search terms to package so customer can retrieve packages with default or
	 * their own specific prices.
	 * (ex: Package which will be hidden fro Customer 1 because default price
	 * is hidden can be visible for Customer 2 because specific prices are set for that customer)
	 *
	 * @param int $owner_id
	 * @param int $package_id
	 * @param array $cl_extras {
	 *			        $extra_price_payment_type =>  {
	 *                      @type bool visible      Indicates if payment type is visible to customer
	 *                  }
     *               }
	 * @param array $old_cl_extras {
	 *			        $extra_price_payment_type =>  {
	 *                      @type bool visible      Indicates if payment type is visible to customer
	 *                  }
	 *               }
	 */
	public static function update_package_prices_search_terms($owner_id, $package_id, $cl_extras, $old_cl_extras) {
		// remove pricing terms for previous prices
		if (! empty($old_cl_extras)) {

			$old_terms = self::_get_search_terms_from_cl_extras($owner_id, $old_cl_extras);

			wp_remove_object_terms($package_id, $old_terms, '_wiaas_shop_prices');
		}

		$new_terms = self::_get_search_terms_from_cl_extras($owner_id, $cl_extras);

		// create term for every visible pricing type and link them to package so package can be queried
		wp_add_object_terms($package_id, $new_terms, '_wiaas_shop_prices');
	}

	// PRIVATE

	/**
	 * Each shop will be registered as product attribute.
	 * This will persist shops information into database.
	 * Also every attribute has taxonomy associated with it which will enable us to have multiple
	 * catalogues in one shop
	 *
	 * @param int $owner_id
	 */
	private static function _maybe_create_shop($owner_id) {
		$shop_name = 'wiaas_shop_' . $owner_id;

		$attribute_id = wc_attribute_taxonomy_id_by_name($shop_name);

		if ($attribute_id === 0) {
			// create shop attribute
			wc_create_attribute(array( 'slug' => $shop_name, 'name' => 'Shop' ));

			$taxonomy_name = wc_attribute_taxonomy_name($shop_name);

			// since  attribute taxonomies are registered once on load
			// we will register new attribute taxonomy here so default catalogue can be added
			register_taxonomy($taxonomy_name, array('product'));

			// add default catalogue option to shop
			wp_insert_term( 'Default Catalogue', $taxonomy_name);
		}
	}

	/**
	 * Deleted associated attribute for shop. This will effectively remove shop and all of its potential catalogues
	 *
	 * @param int $owner_id
	 */
	private static function _maybe_remove_shop($owner_id) {
		// get corresponding attribute for shop
		$attribute_id = wc_attribute_taxonomy_id_by_name('wiaas_shop_' . $owner_id);

		// if shop attribute exists then remove it
		if ($attribute_id > 0) {
			wc_delete_attribute($attribute_id);
		}

		Wiaas_Shop_DB::remove_shop($owner_id);
	}

	/**
	 * Generate search terms from cl extras
	 *
	 * For default prices search term
	 * `_{owner_id}_default` will be generated if all set prices are visible
	 *
	 * For every customer entry search term
	 * `_{owner_id}_customer_{customer_id}_visible` will be generated if any of the prices is visible or
	 * `_{owner_id}_customer_{customer_id}_hidden` if all prices are hidden`
	 *
	 * @param int $owner_id
	 * @param array $cl_extras
	 *
	 * @return array
	 */
	private static function _get_search_terms_from_cl_extras($owner_id, $cl_extras) {
		// determine if extras are visible grouped by customer and default settings
		$cl_extras_per_customer = array();
		$cl_extra_default = false;

		foreach ($cl_extras as $cl_extra_type => $cl_extra) {
			// is default
			if (strpos($cl_extra_type, '_default') !== false) {
				// determine if default cl extra is visible
				$cl_extra_default = $cl_extra_default || $cl_extra['visible'];
			}
			// is customer specific
			if (strpos($cl_extra_type, '_customer_') !== false) {
				$customer_id = absint(explode('_customer_', $cl_extra_type)[1]);
				// determine if customer cl extra is visible
				$cl_extras_per_customer[$customer_id] = $cl_extras_per_customer[$customer_id] || $cl_extra['visible'];
			}
		}

		$terms = array();

		if ($cl_extra_default) {
			$terms[] = '_' . $owner_id . '_default';
		}

		foreach ($cl_extras_per_customer as $customer_id => $visible) {

			$terms[] = '_' . $owner_id . '_customer_' . $customer_id . '_' .
			               ($visible ? 'visible' : 'hidden');
		}

		return $terms;
	}
}

Wiaas_Shop::init();
