<?php
namespace App\Utils\PartnerGroups;

/**
 * This class is used by RD tables also. In case of changes, please take a look on reports
 */
abstract class GeneralAbstract
{
	/**
	 * The partner type (corporate|supplier).
	 * @var string
	 */
	protected $partnerType;

	/**
	 * The database table name.
	 * @var string
	 */
	protected $dbTableName;

	/**
	 * The partner column name.
	 * @var string
	 */
	protected $partnerColumnName;

	/**
	 * The associative list of group elements
	 */
	protected $groupElementsStructured = null;


	/**
	 * Validates main stuff related to the current entity operations.
	 * @throws \Exception
	 */
	public function __construct()
	{
		// set and check the table details
		$this->dbTableName = $this->getDbTableName();
		if (!$this->dbTableName) {
			throw new \Exception('The `dbTableName` field is not set for class '.get_called_class());
		}

		if (!$this->partnerColumnName) {
			throw new \Exception('The `partnerColumnName` field is not set for class '.get_called_class());
		}
	}

	/**
	 * The grouped elements are received in the correct internal structure: [idGroup][idElem1, idElem2, ...]
	 * @param array $groupElementsStructured
	 */
	public function setGroupElementsStructured(array $groupElementsStructured)
	{
		$this->groupElementsStructured = $groupElementsStructured;
	}

	/**
	 * Select the partner ids list associated to the idGroupElements
	 * @throws \DBException
	 */
	public function getPartnerIdsList()
	{

		if ($this->groupElementsStructured===null) {
			throw new \Exception('You must call `setGroupElementsLinear()` or `setGroupElementsStructured()` before calling `getPartnerIdsList()`.');
		}

		$db = \DB::getInstance();

		$selectSQL = "SELECT DISTINCT `{$this->partnerColumnName}` FROM `{$this->dbTableName}` AS `main` WHERE 1";
		foreach ($this->groupElementsStructured as $groupElements) {
			$groupName = uniqid("group_");
			$selectSQL .= " AND EXISTS (SELECT DISTINCT `{$this->partnerColumnName}` FROM `{$this->dbTableName}` as `{$groupName}` WHERE main.{$this->partnerColumnName} = {$groupName}.{$this->partnerColumnName} AND `idGroupElement` IN (".implode(',', array_map(function($str){return "'".$str."'";}, $groupElements))."))";
		}

		$partners = $db->getAll($selectSQL);

		if ($db->ErrorNo()) {
			throw new \DBException('The record could not be selected: '.$db->ErrorMsg());
		}

		$partnerIdsList = [];
		foreach ($partners as $partner) {
			$partnerIdsList[] = $partner[$this->partnerColumnName];
		}

		return $partnerIdsList;
	}

	/**
	 * Returns the table name that stores the current entity records.
	 * @return string
	 */
	abstract protected function getDbTableName();

	/**
	 * Receives an unidimensional array of group elements ids.
	 * @param array $groupElementsLinear
	 */
	public function setGroupElementsLinear(array $groupElementsLinear)
	{
		$elementsStructured = [];
		foreach ($groupElementsLinear as $idGroupElem) {
			if ($this->partnerType=='corporate') {
				$elementDetails = \App\Config\CorporateGroups::getInstance()->getGroupElementDetailsById($idGroupElem);
			}
			elseif ($this->partnerType=='supplier') {
				$elementDetails = \App\Config\SupplierGroups::getInstance()->getGroupElementDetailsById($idGroupElem);
			}

			$elementsStructured[$elementDetails['idGroup']][] = $idGroupElem;
		}
		$this->groupElementsStructured = $elementsStructured;
	}
}
