<?php declare(strict_types = 0);
/*
** Copyright (C) 2001-2025 Zabbix SIA
**
** This program is free software: you can redistribute it and/or modify it under the terms of
** the GNU Affero General Public License as published by the Free Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
** See the GNU Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License along with this program.
** If not, see <https://www.gnu.org/licenses/>.
**/


namespace Widgets\PieChart\Includes;

use CButton,
	CButtonIcon,
	CButtonLink,
	CCol,
	CColor,
	CDiv,
	CFormField,
	CFormGrid,
	CHorList,
	CItemHelper,
	CLabel,
	CLink,
	CList,
	CListItem,
	CPatternSelect,
	CRow,
	CSelect,
	CSimpleButton,
	CSpan,
	CTable,
	CTableColumn,
	CTag,
	CTemplateTag,
	CTextBox,
	CVar,
	CWidgetFieldView;

use Zabbix\Widgets\CWidgetField;

class CWidgetFieldDataSetView extends CWidgetFieldView {

	public function __construct(CWidgetFieldDataSet $field) {
		$this->field = $field;
	}

	public function getView(): CList {
		$view = (new CList())->setId('data_sets');

		$values = $this->field->getValue();

		if (!$values) {
			$values[] = CWidgetFieldDataSet::getDefaults();
		}

		// Get item names for single item datasets.
		$itemids = [];

		foreach (array_column($values, 'itemids') as $items_spec) {
			foreach ($items_spec as $item_spec) {
				if (!is_array($item_spec)) {
					$itemids[$item_spec] = true;
				}
			}
		}

		$item_names = $itemids
			? CWidgetFieldDataSet::getItemNames(array_keys($itemids), !$this->field->isTemplateDashboard())
			: [];

		foreach ($values as $i => $value) {
			if ($value['dataset_type'] == CWidgetFieldDataSet::DATASET_TYPE_SINGLE_ITEM) {
				$value['item_names'] = $item_names;
			}

			$view->addItem(
				$this->getDataSetLayout($value, $value['dataset_type'], $i == 0, $i)
			);
		}

		return $view;
	}

	public function getFooterView(): CList {
		return (new CList())
			->addClass(ZBX_STYLE_BTN_SPLIT)
			->addItem(
				(new CSimpleButton(_('Add new data set')))
					->setId('dataset-add')
					->addClass(ZBX_STYLE_BTN_ALT)
					->addClass(ZBX_ICON_PLUS_SMALL)
			)
			->addItem(
				(new CSimpleButton())
					->setId('dataset-menu')
					->addClass(ZBX_STYLE_BTN_ALT)
					->addClass(ZBX_ICON_CHEVRON_DOWN_SMALL)
			);
	}

	public function getTemplates(): array {
		$value = ['color' => '#{color}'] + CWidgetFieldDataSet::getDefaults();

		return [
			new CTemplateTag('dataset-pattern-item-tmpl',
				$this->getDataSetLayout($value, CWidgetFieldDataSet::DATASET_TYPE_PATTERN_ITEM, true)
			),
			new CTemplateTag('dataset-single-item-tmpl',
				$this->getDataSetLayout($value, CWidgetFieldDataSet::DATASET_TYPE_SINGLE_ITEM, true)
			),
			new CTemplateTag('dataset-item-row-tmpl', $this->getItemRowTemplate())
		];
	}

	private function getDataSetLayout(array $value, int $dataset_type, bool $is_opened,
			$row_num = '#{rowNum}'): CListItem {
		$field_name = $this->field->getName();

		$dataset_head = [
			new CDiv(
				(new CButtonIcon(ZBX_ICON_CHEVRON_UP))->addClass(ZBX_STYLE_LIST_ACCORDION_ITEM_TOGGLE)
			),
			new CVar($field_name.'['.$row_num.'][dataset_type]', $dataset_type, '')
		];

		if ($dataset_type == CWidgetFieldDataSet::DATASET_TYPE_PATTERN_ITEM) {
			if ($this->field->isTemplateDashboard()) {
				$host_pattern_field = null;

				$item_pattern_field = (new CPatternSelect([
					'name' => $field_name.'['.$row_num.'][items][]',
					'object_name' => 'items',
					'data' => $value['items'],
					'placeholder' => _('item patterns'),
					'wildcard_allowed' => 1,
					'popup' => [
						'parameters' => [
							'srctbl' => 'items',
							'srcfld1' => 'name',
							'hostid' => $this->field->getTemplateId(),
							'hide_host_filter' => true,
							'numeric' => 1,
							'dstfrm' => $this->form_name,
							'dstfld1' => zbx_formatDomId($field_name.'['.$row_num.'][items][]')
						]
					],
					'add_post_js' => false
				]))->addClass('js-items-multiselect');
			}
			else {
				$host_pattern_field = (new CPatternSelect([
					'name' => $field_name.'['.$row_num.'][hosts][]',
					'object_name' => 'hosts',
					'data' => $value['hosts'],
					'placeholder' => _('host patterns'),
					'wildcard_allowed' => 1,
					'popup' => [
						'parameters' => [
							'srctbl' => 'hosts',
							'srcfld1' => 'host',
							'dstfrm' => $this->form_name,
							'dstfld1' => zbx_formatDomId($field_name.'['.$row_num.'][hosts][]')
						]
					],
					'add_post_js' => false
				]))->addClass('js-hosts-multiselect');

				$item_pattern_field = (new CPatternSelect([
					'name' => $field_name.'['.$row_num.'][items][]',
					'object_name' => 'items',
					'data' => $value['items'],
					'placeholder' => _('item patterns'),
					'wildcard_allowed' => 1,
					'popup' => [
						'parameters' => [
							'srctbl' => 'items',
							'srcfld1' => 'name',
							'real_hosts' => 1,
							'numeric' => 1,
							'resolve_macros' => 1,
							'dstfrm' => $this->form_name,
							'dstfld1' => zbx_formatDomId($field_name.'['.$row_num.'][items][]')
						],
						'filter_preselect' => [
							'id' => $host_pattern_field->getId(),
							'submit_as' => 'host_pattern',
							'submit_parameters' => [
								'host_pattern_wildcard_allowed' => 1,
								'host_pattern_multiple' => 1
							],
							'multiple' => true
						]
					],
					'autosuggest' => [
						'filter_preselect' => [
							'id' => $host_pattern_field->getId(),
							'submit_as' => 'host_pattern',
							'submit_parameters' => [
								'host_pattern_wildcard_allowed' => 1,
								'host_pattern_multiple' => 1
							],
							'multiple' => true
						]
					],
					'add_post_js' => false
				]))->addClass('js-items-multiselect');
			}

			$dataset_head = array_merge($dataset_head, [
				(new CColor($field_name.'['.$row_num.'][color]', $value['color']))->appendColorPickerJs(false),
				$host_pattern_field,
				$item_pattern_field
			]);
		}
		else {
			$item_rows = [];

			foreach ($value['itemids'] as $i => $item_spec) {
				if (is_array($item_spec)) {
					$itemid = '0';
					$item_reference = $item_spec[CWidgetField::FOREIGN_REFERENCE_KEY];
					$item_name = '';
				}
				else {
					$itemid = $item_spec;
					$item_reference = '';
					$item_name = array_key_exists($itemid, $value['item_names']) ? $value['item_names'][$itemid] : '';
				}

				$item_rows[] = $this->getItemRowTemplate($row_num, ($i + 1), $itemid, $item_reference, $item_name,
					$value['color'][$i], $value['type'][$i]
				);
			}

			$empty_msg_block = (new CDiv(_('No item selected.')))->addClass('no-items-message');

			$items_list = (new CTable())
				->addClass('single-item-table')
				->setAttribute('data-set', $row_num)
				->setColumns([
					(new CTableColumn())->addClass('table-col-handle'),
					(new CTableColumn())->addClass('table-col-color'),
					(new CTableColumn())->addClass('table-col-no'),
					(new CTableColumn(_('Name')))->addClass('table-col-name'),
					(new CTableColumn(_('Type')))->addClass('table-col-type'),
					(new CTableColumn(_('Action')))->addClass('table-col-action')
				])
				->addItem($item_rows)
				->addItem(
					(new CTag('tfoot', true,
						(new CCol(
							new CHorList([
								(new CButtonLink(_('Add item')))->addClass('js-add-item'),
								(new CButtonLink(_('Add widget')))->addClass('js-add-widget')
							])
						))->setColSpan(5)
					))
				);

			$dataset_head = array_merge($dataset_head, [
				(new CDiv([$empty_msg_block, $items_list]))->addClass('items-list table-forms-separator')
			]);
		}

		$dataset_head[] = (new CDiv(
			(new CButtonIcon(ZBX_ICON_REMOVE_SMALLER, _('Delete')))->addClass('js-remove')
		))->addClass('list-item-actions');

		return (new CListItem([
			(new CDiv())
				->addClass(ZBX_STYLE_DRAG_ICON)
				->addClass('js-main-drag-icon'),
			(new CLabel(''))->addClass('js-dataset-label'),
			(new CDiv())
				->addClass(ZBX_STYLE_LIST_ACCORDION_ITEM_HEAD)
				->addClass('dataset-head')
				->addItem($dataset_head),
			(new CDiv())
				->addClass(ZBX_STYLE_LIST_ACCORDION_ITEM_BODY)
				->addClass('dataset-body')
				->addItem([
					(new CFormGrid())
						->addItem([
							new CLabel([
								_('Aggregation function'),
								makeHelpIcon(_('Aggregates each item in the data set.'))
							], 'label-'.$field_name.'_'.$row_num.'_aggregate_function'),
							new CFormField(
								(new CSelect($field_name.'['.$row_num.'][aggregate_function]'))
									->setId($field_name.'_'.$row_num.'_aggregate_function')
									->setFocusableElementId('label-'.$field_name.'_'.$row_num.'_aggregate_function')
									->setValue((int) $value['aggregate_function'])
									->addOptions(CSelect::createOptionsFromArray([
										AGGREGATE_LAST => CItemHelper::getAggregateFunctionName(AGGREGATE_LAST),
										AGGREGATE_MIN => CItemHelper::getAggregateFunctionName(AGGREGATE_MIN),
										AGGREGATE_MAX => CItemHelper::getAggregateFunctionName(AGGREGATE_MAX),
										AGGREGATE_AVG => CItemHelper::getAggregateFunctionName(AGGREGATE_AVG),
										AGGREGATE_COUNT => CItemHelper::getAggregateFunctionName(AGGREGATE_COUNT),
										AGGREGATE_SUM => CItemHelper::getAggregateFunctionName(AGGREGATE_SUM),
										AGGREGATE_FIRST => CItemHelper::getAggregateFunctionName(AGGREGATE_FIRST)
									]))
									->setWidth(ZBX_TEXTAREA_TINY_WIDTH)
							)
						])
						->addItem([
							new CLabel([
								_('Data set aggregation'),
								makeHelpIcon(_('Aggregates the whole data set.'))
							], 'label-'.$field_name.'_'.$row_num.'_dataset_aggregation'),
							new CFormField(
								(new CSelect($field_name.'['.$row_num.'][dataset_aggregation]'))
									->setId($field_name.'_'.$row_num.'_dataset_aggregation')
									->setFocusableElementId('label-'.$field_name.'_'.$row_num.'_dataset_aggregation')
									->setValue((int) $value['dataset_aggregation'])
									->addOptions(CSelect::createOptionsFromArray([
										AGGREGATE_NONE => CItemHelper::getAggregateFunctionName(AGGREGATE_NONE),
										AGGREGATE_MIN => CItemHelper::getAggregateFunctionName(AGGREGATE_MIN),
										AGGREGATE_MAX => CItemHelper::getAggregateFunctionName(AGGREGATE_MAX),
										AGGREGATE_AVG => CItemHelper::getAggregateFunctionName(AGGREGATE_AVG),
										AGGREGATE_COUNT => CItemHelper::getAggregateFunctionName(AGGREGATE_COUNT),
										AGGREGATE_SUM => CItemHelper::getAggregateFunctionName(AGGREGATE_SUM)
									]))
									->setWidth(ZBX_TEXTAREA_TINY_WIDTH)
							)
						])
						->addItem([
							new CLabel([
								_('Data set label'),
								makeHelpIcon(_('Also used as legend label for aggregated data sets.'))
							], $field_name.'_'.$row_num.'_data_set_label'),
							new CFormField(
								(new CTextBox($field_name.'['.$row_num.'][data_set_label]', $value['data_set_label']))
									->setId($field_name.'_'.$row_num.'_data_set_label')
									->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH)
							)
						])
				])
		]))
			->addClass(ZBX_STYLE_LIST_ACCORDION_ITEM)
			->addClass($is_opened ? ZBX_STYLE_LIST_ACCORDION_ITEM_OPENED : ZBX_STYLE_LIST_ACCORDION_ITEM_CLOSED)
			->setAttribute('data-set', $row_num)
			->setAttribute('data-type', $dataset_type);
	}

	private function getItemRowTemplate($ds_num = '#{dsNum}', $row_num = '#{rowNum}', $itemid = '#{itemid}',
			$reference = '#{reference}', $name = '#{name}', $color = '#{color}', $type = '#{type}'): CRow {
		return (new CRow([
			(new CCol((new CDiv())->addClass(ZBX_STYLE_DRAG_ICON)))
				->addClass('table-col-handle')
				->addClass(ZBX_STYLE_TD_DRAG_ICON),
			(new CCol(
				(new CColor($this->field->getName().'['.$ds_num.'][color][]', $color,
					'items_'.$ds_num.'_'.$row_num.'_color'
				))->appendColorPickerJs(false)
			))->addClass('table-col-color'),
			(new CCol(new CSpan($row_num.':')))->addClass('table-col-no'),
			(new CCol([
				(new CSpan())
					->addClass('reference-hint')
					->addClass(ZBX_ICON_REFERENCE)
					->addClass(ZBX_STYLE_DISPLAY_NONE)
					->setHint(_('Another widget is used as data source.')),
				(new CLink($name))
					->setId('items_'.$ds_num.'_'.$row_num.'_name')
					->addClass('js-click-expand')
			]))->addClass('table-col-name'),
			(new CCol([
				(new CSelect($this->field->getName().'['.$ds_num.'][type][]'))
					->setId('items_'.$ds_num.'_'.$row_num.'_type')
					->setValue($type)
					->addOptions(CSelect::createOptionsFromArray([
						CWidgetFieldDataSet::ITEM_TYPE_NORMAL => _('Normal'),
						CWidgetFieldDataSet::ITEM_TYPE_TOTAL => _('Total')
					]))
			]))->addClass('table-col-type'),
			(new CCol([
				(new CButton('button', _('Remove')))
					->addClass(ZBX_STYLE_BTN_LINK)
					->addClass('element-table-remove'),
				new CVar($this->field->getName().'['.$ds_num.'][itemids][]', $itemid,
					'items_'.$ds_num.'_'.$row_num.'_itemid'
				),
				new CVar($this->field->getName().'['.$ds_num.'][references][]', $reference,
					'items_'.$ds_num.'_'.$row_num.'_reference'
				)
			]))
				->addClass('table-col-action')
				->addClass(ZBX_STYLE_NOWRAP)
		]))->addClass('single-item-table-row');
	}
}