<?php

namespace idoit\Module\Customfields\Controller;

use Exception;
use idoit\Module\Cmdb\Component\Table\Config\Refresher;
use idoit\Module\CustomFields\PropertyTypes;
use isys_application;
use isys_component_constant_manager;
use isys_custom_fields_dao;
use isys_format_json;
use isys_helper_link;
use isys_notify;
use isys_register;

class Ajax extends Main
{
    protected $response = null;

    public function handle(isys_register $request, isys_application $application)
    {
        return null;
    }

    public function pre()
    {
        header('Content-Type: application/json');

        $this->response = [
            'success' => true,
            'data'    => null,
            'message' => ''
        ];
    }

    /**
     * Load custom category fields.
     *
     * @param isys_register $request
     *
     * @return void
     */
    public function load(isys_register $request)
    {
        try {
            $result = [];
            $id = (int)$request->get('POST')->get('id');

            $language = $this->getDi()->get('language');
            $database = $this->getDi()->get('database');

            $serializedFieldConfiguration = isys_custom_fields_dao::instance($database)
                ->get_data($id)
                ->get_row_value('isysgui_catg_custom__config');

            $fieldConfiguration = unserialize($serializedFieldConfiguration);

            foreach ($fieldConfiguration as $key => $field) {
                $field['key'] = $key;
                $field['show_in_list'] = (bool)$field['show_in_list'];
                $field['show_inline'] = (bool)$field['show_inline'];
                $field['disable'] = true;

                // This is necessary to determine the correct object browser.
                if ($field['type'] === 'f_popup' && $field['popup'] === 'browser_object') {
                    $field['relation'] = (isset($field['identifier']) && $field['identifier'] > 0) ? 1 : 0;
                }

                $field['configValue'] = PropertyTypes::getTypeByConfiguration($field, $language)['configValue'];

                $result[] = $field;
            }

            $this->response['data'] = $result;
        } catch (\Exception $e) {
            $this->response['success'] = false;
            $this->response['message'] = $e->getMessage();
        }
    }

    /**
     * @param isys_register $request
     *
     * @return void
     * @throws \idoit\Exception\JsonException
     */
    public function save(isys_register $request)
    {
        $database = $this->getDi()->get('database');
        $language = $this->getDi()->get('language');
        $htmlPurifier = $this->getDi()->get('htmlpurifier');

        $config = [];
        $l_dao = new isys_custom_fields_dao($database);

        $id = (int)$request->get('POST')->get('id');
        $properties = isys_format_json::decode($request->get('POST')->get('properties'));
        $title = $request->get('POST')->get('categoryTitle');
        $multivalued = $request->get('POST')->get('multivalued');
        $constant = $request->get('POST')->get('categoryConstant');
        $labelPosition = $request->get('POST')->get('labelPosition');
        $objectTypeIds = explode(',', $request->get('POST')->get('assignedObjectTypes'));

        foreach ($properties as $property) {
            /*
             * Removing line breaks and tabs to prevent that the config can not be loaded.
             * Key fields should not have any line breaks or tabs.
             */
            if (!in_array($property['configValue'], ['script', 'html'])) {
                $property['title'] = str_replace(["\r", "\n", "\t"], '', $property['title']);
            }

            /*
             * This is necessary, for one reason:
             *
             * If we don't pre- or append a string the key will be an integer. This is a problem because:
             * When we serialize integers errors might appear, when we change from a 32 to a 64 bit machine!
             */
            $key = 'c_' . ltrim($property['key'], 'c_');

            // If type contains a comma, its a popup which needs more infos.
            if (false !== strpos($property['configValue'], ',')) {
                $data = explode(',', $property['configValue']);

                if ($data[1] === 'yes-no') {
                    $config[$key] = [
                        'type'    => $data[0],
                        'extra'   => $data[1],
                        'title'   => $property['title'],
                        'default' => $property['default']
                    ];
                } elseif ($data[1] === 'date-datetime') {
                    $config[$key] = [
                        'type'    => $data[0],
                        'popup'   => $data[2],
                        'extra'   => $data[1],
                        'title'   => $property['title'],
                        'default' => $property['default']
                    ];
                } else {
                    $config[$key] = [
                        'type'  => $data[0],
                        'popup' => $data[1],
                        'title' => $property['title']
                    ];
                }

                // Dialog or Dialog+?
                if (in_array($data[1], ['dialog', 'dialog_plus', 'report_browser', 'checkboxes'], true)) {
                    if (isset($property['identifier'])) {
                        if (empty($property['identifier']) && $data[1] != 'report_browser') {
                            $property['identifier'] = isys_glob_strip_accent(isys_glob_replace_accent($property['title']), '_');
                        }

                        $config[$key]["identifier"] = $property['identifier'];
                    }

                    if ($data[2] == 1) {
                        $config[$key]['multiselection'] = true;
                    }

                    // Check if we need to process dependency data.
                    if ($data[1] === 'dialog_plus' && isset($property['dialogDependency'], $property['dialogLinkedTo'])) {
                        // Multiselect dialog+ is only allowed to be "secondary" (= it can only depend on a single value dialog+).
                        if ($data[2] == 1) {
                        } else {
                        }

                        $config[$key]['dialogDependency'] = $property['dialogDependency'];
                        $config[$key]['dialogLinkedTo'] = $property['dialogLinkedTo'];
                    }
                }

                // Normal Object browser or with relation?
                if ($data[1] === 'browser_object') {
                    if ($data[2] == 1) {
                        $config[$key]["identifier"] = $property['identifier'];
                    }

                    if ($data[3] == 1) {
                        $config[$key]['multiselection'] = true;
                    }
                }
            } else {
                $config[$key] = [
                    "type"  => $property['configValue'],
                    "title" => $htmlPurifier->purify($property['title'])
                ];
            }

            if (isset($property['visibility'])) {
                $config[$key]['visibility'] = $property['visibility'];
            }

            // Save show_in_list config.
            $config[$key]['show_in_list'] = isset($property['show_in_list']) && $property['show_in_list'];

            // @see  ID-641  Save the 'inline' configuration.
            $config[$key]['show_inline'] = $property['show_inline'];
        }

        if (isset($config) && is_countable($config) && count($config) > 0) {
            try {
                if (!$l_dao->validateTitle($title)) {
                    throw new Exception($language->get('LC__MODULE__QCW__CREATE_CUSTOM_CATEGORY_VALIDATION'));
                }

                if (is_numeric($id) && $id > 0) {
                    $l_dao->save($id, $title, $config, 0, 0, $multivalued, $constant, $labelPosition);
                } else {
                    $id = $l_dao->create($title, $config, 0, 0, $multivalued, $constant, $labelPosition);

                    if (!is_numeric($id)) {
                        throw new Exception($language->get('LC__CMDB__OBJECT_BROWSER__SCRIPT__OBJECT_DATA_LOAD_ERROR'));
                    }
                }

                // Clear all object type assignments.
                $l_dao->clear_assignments($id);

                // Add Generic template.
                if (defined('C__OBJTYPE__GENERIC_TEMPLATE')) {
                    if (!in_array(C__OBJTYPE__GENERIC_TEMPLATE, $objectTypeIds)) {
                        $objectTypeIds[] = C__OBJTYPE__GENERIC_TEMPLATE;
                    }
                }

                if (is_array($objectTypeIds)) {
                    foreach ($objectTypeIds as $objectTypeId) {
                        if ($objectTypeId > 0) {
                            $l_dao->assign($id, $objectTypeId);
                        }
                    }

                    $l_dao->clearUnassignedOverviewTypes($id, $objectTypeIds);
                }

                // Update constant cache:
                isys_component_constant_manager::instance()->clear_dcm_cache();

                // @see  ID-6382  Refresh the table configurations of the assigned object types.
                $refresher = new Refresher($database);

                $sql = 'SELECT GROUP_CONCAT(isys_obj_type__const) AS constantList 
                    FROM isys_obj_type 
                    WHERE isys_obj_type__id ' . $l_dao->prepare_in_condition($objectTypeIds) . ';';

                $constantList = $l_dao->retrieve($sql)->get_row_value('constantList');

                $objectTypeConstants = explode(',', $constantList);

                foreach ($objectTypeConstants as $objectTypeConstant) {
                    $refresher->processByObjectTypeConstant($objectTypeConstant);
                }

                // Return a redirect URL so the configuration gets "reloaded".
                $this->response['data'] = [
                    'redirectUrl' => isys_helper_link::create_url([
                        C__GET__MODULE_ID     => C__MODULE__SYSTEM,
                        C__GET__MODULE_SUB_ID => C__MODULE__CUSTOM_FIELDS,
                        C__GET__TREE_NODE     => C__MODULE__CUSTOM_FIELDS . 1,
                        C__GET__ID            => $id
                    ])
                ];

                isys_notify::success($language->get('LC__INFOBOX__DATA_WAS_SAVED'));
            } catch (Exception $e) {
                isys_application::instance()->container->get('notify')->error($e->getMessage(), ['sticky' => true]);
                $this->response['success'] = false;
                $this->response['message'] = $e->getMessage();
            }
        } else {
            isys_application::instance()->container->get('notify')->error("Specify your fields, please.");
            $this->response['success'] = false;
            $this->response['message'] = 'Specify your fields, please.';
        }
    }

    public function post()
    {
        echo isys_format_json::encode($this->response);
        die;
    }
}
