<?php

namespace idoit\Module\Cmdb\Component\CategoryChanges\Type\Browser;

use idoit\Component\Property\Property;
use idoit\Module\Cmdb\Component\CategoryChanges\Data\ChangesData;
use idoit\Module\Cmdb\Component\CategoryChanges\Data\DataProvider;
use idoit\Module\Cmdb\Component\CategoryChanges\Data\DefaultData;
use idoit\Module\Cmdb\Component\CategoryChanges\Data\RequestData;
use idoit\Module\Cmdb\Component\CategoryChanges\Data\SmartyData;
use idoit\Module\Cmdb\Component\CategoryChanges\Type\TypeInterface;
use isys_cmdb_dao;
use isys_cmdb_dao_category;
use isys_popup_browser_object_ng;
use isys_tenantsettings;

/**
 * Class ObjectBrowserType
 *
 * Handles changes for property types for normal Object-Browsers
 *
 * @package idoit\Module\Cmdb\Component\CategoryChanges\Type
 */
class ObjectBrowserType extends AbstractBrowserType implements TypeInterface, ObjectBrowserTypeInterface
{
    /**
     * @param Property $property
     * @param string   $tag
     *
     * @return bool
     */
    public function isApplicable(Property $property, string $tag)
    {
        $ignoreObjectBrowserWithCallback = [
            'cable_connection'
        ];

        $callback = $property->getFormat()->getCallback();
        $callbackFunc = !empty($callback) ? $callback[1] : '';
        $params = $property->getUi()->getParams();

        return $property->getInfo()->getType() === Property::C__PROPERTY__INFO__TYPE__OBJECT_BROWSER &&
            $params['p_strPopupType'] === 'browser_object_ng' &&
            !!$params[isys_popup_browser_object_ng::C__SECOND_SELECTION] === false &&
            !!$params[isys_popup_browser_object_ng::C__MULTISELECTION] === false &&
            !in_array($callbackFunc, $ignoreObjectBrowserWithCallback);
    }

    /**
     * @param string                 $tag
     * @param isys_cmdb_dao_category $dao
     * @param RequestData            $requestDataProvider
     * @param SmartyData             $smartyDataProvider
     * @param array                  $currentData
     *
     * @return array|null
     */
    public function handlePostData(string $tag, isys_cmdb_dao_category $dao, RequestData $requestDataProvider, SmartyData $smartyDataProvider, array $currentData = [])
    {
        $requestData = $requestDataProvider->getData();
        $smartyData = $smartyDataProvider->getData();
        $property = $this->getProperty();
        $uiField = $property->getUi()->getId();
        $uiHiddenField = $uiField . '__HIDDEN';
        $uiViewField = $uiField . '__VIEW';
        $uiConfigField = $uiField . '__CONFIG';
        $currentObjectId = $dao->get_object_id();
        $currentPropertyTag = $this->getCurrentPropertyTag($dao, $tag);
        $alwaysInLogbook = $property->getInfo()->isAlwaysInLogbook();
        $changes = [];

        $newValue = $requestData[$uiField];
        $newValueId = (int)$requestData[$uiHiddenField];
        $oldValueId = (int)(!empty($smartyData[$uiField]['p_strSelectedID']) ?
            $smartyData[$uiField]['p_strSelectedID'] : (is_numeric($smartyData[$uiField]['p_strValue']) ? $smartyData[$uiField]['p_strValue'] : ''));
        $oldValueConfig = \isys_format_json::is_json_array($requestData[$uiConfigField]) ?
            \isys_format_json::decode($requestData[$uiConfigField]) : [];
        $oldValue = $oldValueConfig['p_strValue'] ?? '';
        $this->setBackwardPropertyTag($property->getInfo()->getBackwardProperty() ?: null);

        if ($newValueId === $oldValueId && !$alwaysInLogbook) {
            return [];
        }

        if ($newValueId === $oldValueId && $this->getBackwardPropertyTag() !== null && !$alwaysInLogbook) {
            $this->setToObjectId($newValueId);
            $changes[self::CHANGES_TO] = $this->handlePostDataHelper($dao, $currentObjectId, $newValueId, self::CHANGES_BOTH);
            return $changes;
        }

        if ($oldValueId > 0 && $oldValue === '') {
            $oldValue = $this->getObjectTitle($oldValueId, $dao);
        }

        if ($oldValueId !== $newValueId && $this->getBackwardPropertyTag() !== null) {
            $changes[self::CHANGES_FROM] = $this->handlePostDataHelper($dao, $currentObjectId, $oldValueId, self::CHANGES_FROM);
            $this->setFromObjectId($oldValueId);
        }

        if (($newValueId > 0 && $newValueId !== $oldValueId) || $alwaysInLogbook) {
            $changes[self::CHANGES_TO] = $this->handlePostDataHelper($dao, $currentObjectId, $newValueId, self::CHANGES_TO);
            $this->setToObjectId($newValueId);
        }

        $currentChanges = [
            self::CHANGES_CURRENT => ChangesData::factory(
                [
                    $currentPropertyTag => [
                        self::CHANGES_FROM => $oldValue,
                        self::CHANGES_TO   => $newValue
                    ]
                ],
                $dao->get_object_id()
            )
        ];

        $changes =  $currentChanges + $changes;
        return $changes;
    }

    /**
     * @param isys_cmdb_dao_category $dao
     * @param int                    $objectId
     * @param int                    $referenceId
     * @param string                 $direction
     *
     * @return ChangesData
     * @throws \isys_exception_database
     */
    private function handlePostDataHelper(isys_cmdb_dao_category $dao, $objectId, $referenceId, $direction = self::CHANGES_FROM)
    {
        $currentObjectTitle = '';
        $currentObjectTitle = $this->getObjectTitle($objectId, $dao);
        $backwardProperty = $this->getProperty()->getInfo()->getBackwardProperty();
        $changes = [];

        switch ($direction) {
            case self::CHANGES_FROM:
                $changes[$backwardProperty] =
                    [
                        self::CHANGES_FROM => $currentObjectTitle,
                        self::CHANGES_TO => $this->getLanguage()->get('LC__UNIVERSAL__CONNECTION_DETACHED')
                    ];
                break;
            case self::CHANGES_TO:
                $changes[$backwardProperty] =
                     [
                        self::CHANGES_FROM => '',
                        self::CHANGES_TO => $currentObjectTitle
                    ];
                break;
            case self::CHANGES_BOTH:
                $changes[$backwardProperty] = [
                    self::CHANGES_FROM => $currentObjectTitle,
                    self::CHANGES_TO => $currentObjectTitle
                ];
                break;
        }

        return ChangesData::factory($changes, $referenceId);
    }

    /**
     * @param DefaultData $currentData
     * @param DefaultData $changedData
     *
     * @return array
     */
    public function handleData(DefaultData $currentData, DefaultData $changedData)
    {
        // TODO: Implement handleData() method.
    }

    public function handleRanking()
    {
        // TODO: Implement handleRanking() method.
    }
}
