<?php

namespace idoit\Module\Cmdb\Component\CategoryChanges\Builder;

use idoit\Component\Property\Property;
use idoit\Module\Cmdb\Component\CategoryChanges\Builder\Exception\ProcessWithArrayDataException;
use idoit\Module\Cmdb\Component\CategoryChanges\Builder\Exception\ProcessWithPostDataException;
use idoit\Module\Cmdb\Component\CategoryChanges\Data\DataProvider;
use idoit\Module\Cmdb\Component\CategoryChanges\Data\PropertyData;
use idoit\Module\Cmdb\Component\CategoryChanges\Data\RequestData;
use idoit\Module\Cmdb\Component\CategoryChanges\Data\SmartyData;
use idoit\Module\Cmdb\Component\CategoryChanges\Type\Browser\ObjectBrowserTypeInterface;
use idoit\Module\Cmdb\Component\CategoryChanges\Type\TypeInterface;
use isys_application;
use isys_cmdb_dao_category;
use isys_cmdb_dao_category_g_custom_fields;
use isys_notify;

/**
 * Class ChangesBuilder
 *
 * @package idoit\Module\Cmdb\Component\CategoryChanges\Builder
 */
class ChangesBuilder extends AbstractChangesBuilder
{
    /**
     * @param DataProvider $dataProvider
     *
     * @return bool
     */
    public function process(DataProvider $dataProvider)
    {
        $objectId = $dataProvider->getObjectId();
        $propertyProvider = $dataProvider->getPropertyData();
        $currentDataProvider = $dataProvider->getCurrentData();
        $changedDataProvider = $dataProvider->getChangedData();
        $requestDataProvider = $dataProvider->getRequestData();
        $smartyDataProvider = $dataProvider->getSmartyData();

        try {
            if ($currentDataProvider->hasData() && $changedDataProvider->hasData()) {
                $this->processWithArrayData($dataProvider);
            }

            if ($requestDataProvider->hasData() && $smartyDataProvider->hasData()) {
                $this->processWithRequestData($dataProvider);
            }
        } catch (ProcessWithPostDataException $e) {
            isys_notify::error(
                $e->getMessage(),
                ['sticky' => true]
            );
            return false;
        } catch (ProcessWithArrayDataException $e) {
            isys_notify::error(
                $e->getMessage(),
                ['sticky' => true]
            );
            return false;
        }

        return true;
    }

    /**
     * @param DataProvider $dataProvider
     */
    private function processWithArrayData(DataProvider $dataProvider)
    {
        // Todo implement processing with a sync array data
    }

    /**
     * @param DataProvider $dataProvider
     *
     * @throws ProcessWithPostDataException
     */
    private function processWithRequestData(DataProvider $dataProvider)
    {
        /**
         * @var $daoBackwardsProperty isys_cmdb_dao_category|null
         */
        $propertyProvider = $dataProvider->getPropertyData();
        $currentDataProvider = $dataProvider->getCurrentData();
        $smartyDataProvider = $dataProvider->getSmartyData();
        $requestDataProvider = $dataProvider->getRequestData();
        $currentData = $currentDataProvider->getData();
        $properties = $propertyProvider->getData();
        $dao = $propertyProvider->getDao();
        $daoBackwardsProperty = null;
        $this->getChangesCurrent()->setDao($dao);
        $this->getChangesCurrent()->setObjectId($dataProvider->getObjectId());
        $propertiesIndex = get_class($dao);

        if ($dao instanceof isys_cmdb_dao_category_g_custom_fields) {
            $propertiesIndex .= '::' . $dao->get_catg_custom_id();
        }

        try {
            foreach ($properties[$propertiesIndex] as $tag => $propertyTypeData) {
                /**
                 * @var $propertyTypeData TypeInterface
                 */
                $logbookTag = $propertyTypeData[PropertyData::LOGBOOK_TAG];
                $propertyTypeData = $propertyTypeData[PropertyData::PROPERTY_TYPE_DATA];

                if (!$propertyTypeData instanceof TypeInterface) {
                    continue;
                }

                $changes = $propertyTypeData->handlePostData($tag, $dao, $requestDataProvider, $smartyDataProvider, $currentData);

                if ($propertyTypeData instanceof ObjectBrowserTypeInterface && $propertyTypeData->getBackwardPropertyTag() &&
                    ($propertyTypeData->getFromObjectId() || $propertyTypeData->getToObjectId())) {
                    if ($this->getFromObjectId() === null) {
                        $this->setFromObjectId($propertyTypeData->getFromObjectId());
                    }

                    if ($this->getToObjectId() === null) {
                        $this->setToObjectId($propertyTypeData->getToObjectId());
                    }

                    if ($daoBackwardsProperty === null) {
                        [$daoBackwardsPropertyClass] = explode('::', $propertyTypeData->getBackwardPropertyTag());
                        $daoBackwardsProperty = $daoBackwardsPropertyClass::instance($dao->get_database_component());

                        $this->getChangesFrom()
                            ->setDao($daoBackwardsProperty)
                            ->setObjectId($this->getFromObjectId());
                        $this->getChangesTo()
                            ->setDao($daoBackwardsProperty)
                            ->setObjectId($this->getToObjectId());
                    }
                }
                $this->setChanges($changes);
            }
        } catch (\Exception $e) {
            throw new ProcessWithPostDataException($e->getMessage());
        }

        if ($daoBackwardsProperty === null) {
            $this->getChangesTo()->resetData();
        }
    }
}
