<?php
/**
 *
 *
 * @package     i-doit
 * @subpackage
 * @author      Pavel Abduramanov <pabduramanov@i-doit.com>
 * @copyright   synetics GmbH
 * @license     http://www.i-doit.com/license
 */

namespace idoit\Component\Table\Filter\Operation;

use isys_cmdb_dao_list_objects;
use isys_smarty_plugin_f_dialog;

class DialogSearchOperation extends PropertyOperation
{
    /**
     * @var OperationInterface
     */
    private $fallbackOperation;

    /**
     * DialogSearchOperation constructor.
     *
     * @param OperationInterface $fallbackOperation
     */
    public function __construct(OperationInterface $fallbackOperation)
    {
        $this->fallbackOperation = $fallbackOperation;
    }

    public function isApplicable($filter, $value)
    {
        $property = $this->getProperty($filter);
        if ($property && isset($property[C__PROPERTY__INFO], $property[C__PROPERTY__INFO][C__PROPERTY__INFO__TYPE]) &&
            in_array($property[C__PROPERTY__INFO][C__PROPERTY__INFO__TYPE],
                [C__PROPERTY__INFO__TYPE__DIALOG, C__PROPERTY__INFO__TYPE__DIALOG_PLUS, C__PROPERTY__INFO__TYPE__DIALOG_LIST])) {
            return true;
        }

        return false;
    }

    /**
     * Apply Property
     *
     * @param isys_cmdb_dao_list_objects $listDao
     * @param                            $property
     * @param                            $name
     * @param                            $value
     *
     * @return mixed
     */
    protected function applyProperty(isys_cmdb_dao_list_objects $listDao, $property, $name, $value)
    {
        $items = $this->getItems($property);
        // check if it's a multivalue category
        $class = explode('__', $name)[0];
        if ($class && class_exists($class)) {
            $obj = $class::instance(\isys_application::instance()->container->get('database'));
            if (method_exists($obj, 'is_multivalued') && $obj->is_multivalued()) {
                // if it's an id - get the value from it
                if ($value == (string)(int)$value) {
                    $value = $items[$value] ?: null;
                }
                return $this->fallbackOperation->apply($listDao, $name, $value);
            }
        }

        if ($value == (string)(int)$value) {
            $listDao->add_additional_conditions("AND {$property[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD]} = $value");

            return true;
        }
        if (isset($items)) {
            $items = array_filter($items, function ($item) use ($value) {
                return strlen($value) > 0 && strpos(strtolower($item), strtolower($value)) !== false;
            }, ARRAY_FILTER_USE_BOTH);
            if (count($items)) {
                $ids = implode(',', array_keys($items));
                $listDao->add_additional_conditions("AND {$property[C__PROPERTY__DATA][C__PROPERTY__DATA__FIELD]} IN ({$ids})");
            } else {
                // Nothing is found
                $listDao->add_additional_conditions("AND FALSE");
            }

            return true;
        }

        return false;
    }

    /**
     * Get array data from property
     *
     * @param array $property
     *
     * @return array|mixed
     */
    protected function getItems(array $property)
    {
        if (isset($property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strTable']) && $property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strTable']) {
            $dialog = new isys_smarty_plugin_f_dialog();

            return $dialog->get_array_data($property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_strTable'], C__RECORD_STATUS__NORMAL, null,
                $property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['condition']);
        } elseif (isset($property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData'])) {
            if (is_array($property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData'])) {
                // If we simply get an array.
                return $property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData'];
            } else if (is_object($property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData']) &&
                get_class($property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData']) == 'isys_callback') {
                // If we get an instance of "isys_callback"
                return $property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData']->execute();
            } else if (is_string($property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData'])) {
                // Or if we get a string (we assume it's serialized).
                return unserialize($property[C__PROPERTY__UI][C__PROPERTY__UI__PARAMS]['p_arData']);
            }
        }

        return [];
    }
}