<?php
/**
 * @version     1.4.7
 * @package     sellacious
 *
 * @copyright   Copyright (C) 2012-2017 Bhartiy Web Technologies. All rights reserved.
 * @license     SPL Sellacious Private License; see http://www.sellacious.com/spl.html
 * @author      Izhar Aazmi <info@bhartiy.com> - http://www.bhartiy.com
 */
// no direct access.
defined('_JEXEC') or die;

use Joomla\Utilities\ArrayHelper;

/**
 * Methods supporting a list of Sellacious records.
 *
 * @since  3.0
 */
class SellaciousModelOrders extends SellaciousModelList
{
	/**
	 * @var  stdClass[]
	 */
	protected $items;

	/**
	 * Constructor
	 *
	 * @param   array  $config  An array of configuration options (name, state, dbo, table_path, ignore_request).
	 *
	 * @see     JModelList
	 * @since   3.0
	 */
	public function __construct(array $config)
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'a.id',
				'a.order_number',
				'a.created',
				'ss.title',
				'cu.amount',
				'a.cart_taxes',
				'a.cart_discounts',
				'a.grand_total',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Get the filter form
	 *
	 * @param   array   $data     data
	 * @param   boolean $loadData load current data
	 *
	 * @return  JForm/false  the JForm object or false
	 *
	 * @since   3.2
	 */
	public function getFilterForm($data = array(), $loadData = true)
	{
		$form = parent::getFilterForm($data, $loadData);

		if ($form instanceof JForm)
		{
			if (!$this->helper->access->check('order.list'))
			{
				$form->removeField('seller_uid', 'filter');
			}
		}

		return $form;
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 */
	protected function getListQuery()
	{
		$me    = JFactory::getUser();
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true);

		$query->select('a.*')
			->from($db->qn('#__sellacious_orders', 'a'));

		if ($this->helper->access->check('order.list'))
		{
			if ($seller_uid = $this->state->get('filter.seller_uid'))
			{
				$query->join('left', '#__sellacious_order_items oi ON oi.order_id = a.id')
					->where('oi.seller_uid = ' . (int) $seller_uid)
					->group('a.id');
			}
		}
		elseif ($this->helper->access->check('order.list.own'))
		{
			$query->join('left', '#__sellacious_order_items oi ON oi.order_id = a.id')
				->where('oi.seller_uid = ' . (int) $me->id)
				->group('a.id');
		}
		else
		{
			// Fallacy
			return $query->where('0 = 1');
		}

		$query->select('cu.amount AS coupon_amount, cu.code AS coupon_code')
			->join('left', '#__sellacious_coupon_usage AS cu ON cu.order_id = a.id');

		// Order status
		$query->select('os.status AS order_status_id')
			->join('left', '#__sellacious_order_status AS os ON os.order_id = a.id AND os.state = 1 AND os.item_uid = ' . $db->q(''));

		$query->select('ss.title AS order_status')
			->join('left', '#__sellacious_statuses AS ss ON ss.id = os.status');

		// Payment method name
		$query->select('op.method_name AS payment_method')
			->join('left', '#__sellacious_payments AS op ON op.order_id = a.id AND op.context = ' . $db->q('order') . ' AND op.state > 0');

		if ($search = $this->getState('filter.search'))
		{
			$query->where('a.order_number = '. $db->q($search));
		}

		if ($os = $this->getState('filter.status'))
		{
			$query->where('os.status = '. (int) $os);
		}
		else
		{
			$query->where('ss.type != ' . $db->q('order_placed'));
		}

		$ordering = $this->state->get('list.fullordering', 'a.created DESC');

		if ($ordering)
		{
			$query->order($db->escape($ordering));
		}

		return $query;
	}

	/**
	 * Process list to add items and order status in each order record
	 *
	 * @param   stdClass[] $orders
	 *
	 * @return  stdClass[]
	 */
	protected function processList($orders)
	{
		/** @var  SellaciousTableOrder $oTable */
		$me     = JFactory::getUser();
		$oTable = $this->getTable('Order');

		array_walk($orders, array($oTable, 'parseJson'));

		$allowAll = $this->helper->access->check('order.list');
		$allowOwn = $this->helper->access->check('order.list.own');

		// This test is probably not required here coz,
		// If this would be false there would be no items in the first place.
		if ($allowAll || $allowOwn)
		{
			$oid   = ArrayHelper::getColumn($orders, 'id');
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true);

			$query->select('a.*')
				->from($db->qn('#__sellacious_order_items', 'a'))
				->where('a.order_id IN (' . implode(', ', $db->q($oid)) . ')');

			$query->select('shipper, tracking_url, tracking_number, ship_date, item_serial, ship_notes')
				->select('source_address, source_district, source_state, source_country, source_zip')
				->join('left', '#__sellacious_order_shipments s USING (order_id, item_uid)')
				->group('a.id, a.order_id, a.item_uid');

			if ($seller_uid = $allowAll ? $this->state->get('filter.seller_uid') : (int) $me->id)
			{
				$query->where('a.seller_uid = ' . (int) $seller_uid);
			}

			try
			{
				$db->setQuery($query);
				$o_items_list = array();
				$orders_items = $db->loadObjectList();

				/** @var  SellaciousTableOrderItem  $oiTable */
				$oiTable = $this->getTable('OrderItem');

				foreach ($orders_items as $orders_item)
				{
					$oiTable->parseJson($orders_item);

					$orders_item->package_items = null;

					if ($orders_item->product_type == 'package')
					{
						$filters = array(
							'list.select' => 'a.*',
							'list.from'   => '#__sellacious_order_package_items',
							'list.where'  => 'a.order_item_id = ' . (int) $orders_item->id,
						);

						$orders_item->package_items = (array) $this->helper->order->loadObjectList($filters);
					}

					$o_items_list[$orders_item->order_id][] = $orders_item;
				}

				foreach ($orders as $order)
				{
					$order->items = ArrayHelper::getValue($o_items_list, $order->id, array());
				}
			}
			catch (Exception $e)
			{
				JLog::add($e->getMessage(), JLog::WARNING, 'jerror');
			}
		}

		return parent::processList($orders);
	}
}
