<?php

use idoit\Exception\InvalidCacheDataException;

/**
 * i-doit core classes.
 *
 * @package     i-doit
 * @subpackage  Core
 * @author      Dennis Stücken <dstuecken@synetics.de>
 * @copyright   synetics GmbH
 * @license     http://www.i-doit.com/license
 */
class isys_usersettings implements isys_settings_interface
{
    use isys_settings_trait;

    /**
     * Database component.
     *
     * @var  isys_component_dao_user_settings
     */
    protected static $m_dao;

    /**
     * Settings register.
     *
     * @var  array
     */
    protected static $m_definition = [
        'Quickinfo (Link mouseover)'                                         => [
            'gui.quickinfo.active' => [
                'title'   => 'LC__USER_SETTINGS__QUICKINFO_ACTIVE',
                'type'    => 'select',
                'default' => '1',
                'options' => [
                    0 => 'LC__UNIVERSAL__NO',
                    1 => 'LC__UNIVERSAL__YES'
                ]
            ],
            'gui.quickinfo.delay'  => [
                'title'       => 'LC__UNIVERSAL__DELAY',
                'type'        => 'float',
                'default'     => 0.5,
                'placeholder' => 0.5
            ]
        ],
        'LC__MODULE__SYSTEM__TREE__USER_SETTINGS__VIEWS__LISTS__OBJECT_LIST' => [
            'gui.objectlist.remember-filter' => [
                'title'       => 'LC__CMDB__TREE__SYSTEM__OBJECT_LIST__FILTER_MEMORIZE',
                'type'        => 'int',
                'default'     => 300,
                'placeholder' => 0,
                'description' => 'LC__CMDB__TREE__SYSTEM__OBJECT_LIST__FILTER_MEMORIZE_DESCRIPTION'
            ],
            'gui.objectlist.rows-per-page'   => [
                'title'       => 'LC__SYSTEM__REGISTRY__PAGELIMIT',
                'type'        => 'int',
                'default'     => 50,
                'placeholder' => 50
            ]
        ],
        'LC__MODULE__QCW__CATEGORIES'                                        => [
            'gui.category.cabling.directly-open-cabling-addon' => [
                'title'   => 'LC__CABLING__NEW_VISUALIZATION__ADDON_READY_DIRECTLY_OPEN_IN_ADDON_SETTING',
                'type'    => 'select',
                'options' => [
                    0 => 'LC__UNIVERSAL__NO',
                    1 => 'LC__UNIVERSAL__YES'
                ]
            ]
        ],
        'LC__USER_SETTINGS__HEADER__MAIN_MENU'                               => [
            'gui.show-my-doit'                        => [
                'title'   => 'LC__USER_SETTINGS__SHOW_MY_DOIT',
                'type'    => 'select',
                'options' => [
                    0 => 'LC__UNIVERSAL__NO',
                    1 => 'LC__UNIVERSAL__YES'
                ]
            ],
            'gui.show-object-type-groups-as-dropdown' => [
                'title'   => 'LC__USER_SETTINGS__OBJECT_TYPE_GROUPS_AS_DROPDOWN',
                'type'    => 'select',
                'options' => [
                    0 => 'LC__UNIVERSAL__NO',
                    1 => 'LC__UNIVERSAL__YES',
                    2 => 'LC__USER_SETTINGS__OBJECT_TYPE_GROUPS_AS_DROPDOWN_AUTOMATIC'
                ]
            ]
        ],
        'LC__USER_SETTINGS__HEADER__OBJECT_NAVIGATION'                       => [
            'gui.default-tree-view'            => [
                'title'   => 'LC__CMDB__SETTINGS__USER__DEFAULT_TREEVIEW',
                'type'    => 'select',
                'options' => [
                    C__CMDB__VIEW__TREE_OBJECTTYPE => 'LC__CMDB__OBJECT_VIEW',
                    C__CMDB__VIEW__TREE_LOCATION   => 'LC__CMDB__MENU_TREE_VIEW'
                ]
            ],
            'gui.default-tree-type'            => [
                'title'   => 'LC__CMDB__SETTINGS__USER__DEFAULT_TREETYPE',
                'type'    => 'select',
                'options' => [
                    C__CMDB__VIEW__TREE_LOCATION__LOCATION      => 'LC__CMDB__TREE_VIEW__LOCATION',
                    C__CMDB__VIEW__TREE_LOCATION__LOGICAL_UNITS => 'LC__CMDB__TREE_VIEW__LOGICAL_UNIT',
                    C__CMDB__VIEW__TREE_LOCATION__COMBINED      => 'LC__CMDB__TREE_VIEW__COMBINED',
                ]
            ],
            'gui.tree.hide-empty-object-types' => [
                'title'   => 'LC__USER_SETTINGS__TREE_HIDE_EMPTY_OBJECT_TYPES',
                'type'    => 'select',
                'options' => [
                    0 => 'LC__UNIVERSAL__NO',
                    1 => 'LC__UNIVERSAL__YES',
                ]
            ],
            'gui.tree.hide-empty-categories'   => [
                'title'   => 'LC__USER_SETTINGS__TREE_HIDE_EMPTY_CATEGORIES',
                'type'    => 'select',
                'options' => [
                    0 => 'LC__UNIVERSAL__NO',
                    1 => 'LC__UNIVERSAL__YES',
                ]
            ]
        ],
        'LC__USER_SETTINGS__HEADER__SPACING'                                 => [
            // @see ID-8965 Save user custom row padding.
            'gui.category.padding' => [
                'title'   => 'LC__USER_SETTINGS__CATEGORY_ROW_PADDING',
                'type'    => 'select',
                'options' => [
                    's' => 'LC__USER_SETTINGS__CATEGORY_ROW_PADDING__SMALL',
                    'm' => 'LC__USER_SETTINGS__CATEGORY_ROW_PADDING__MEDIUM',
                    'l' => 'LC__USER_SETTINGS__CATEGORY_ROW_PADDING__LARGE'
                ],
                'default' => 'l',
            ],
            // @see ID-9164 Save tree spacing
            'gui.tree.spacing'     => [
                'title'   => 'LC__USER_SETTINGS__TREE_SPACING',
                'type'    => 'select',
                'options' => [
                    's' => 'LC__USER_SETTINGS__CATEGORY_ROW_PADDING__SMALL',
                    'm' => 'LC__USER_SETTINGS__CATEGORY_ROW_PADDING__MEDIUM',
                    'l' => 'LC__USER_SETTINGS__CATEGORY_ROW_PADDING__LARGE'
                ],
                'default' => 'l',
            ],
            // @see ID-8965 Save if the user wants to see spacers.
            'gui.category.spacer'  => [
                'title'   => 'LC__USER_SETTINGS__CATEGORY_SPACER',
                'type'    => 'select',
                'options' => [
                    0 => 'LC__UNIVERSAL__NO',
                    1 => 'LC__UNIVERSAL__YES',
                ],
                'default' => 1,
            ],
        ]
    ];

    /**
     * Return a system setting
     *
     * @static
     *
     * @param   string $p_key     Setting identifier
     * @param   mixed  $p_default Default value
     *
     * @return  mixed
     */
    public static function get($p_key = null, $p_default = '')
    {
        if ($p_key === null) {
            return self::$m_settings;
        }

        if (isset(self::$m_settings[$p_key]) && self::$m_settings[$p_key] != '') {
            return self::$m_settings[$p_key];
        }

        return isys_tenantsettings::get($p_key, $p_default);
    }

    /**
     * Method for retrieving the cache directory.
     *
     * @static
     * @throws  Exception
     * @return  string
     */
    protected static function get_cache_dir()
    {
        if (empty(self::$m_cache_dir)) {
            $session = isys_application::instance()->container->get('session');

            if (!is_object($session)) {
                throw new Exception('Usersettings are only available after logging in.');
            }

            if (!$session->is_logged_in()) {
                throw new Exception('Usersettings are only available after logging in.');
            }

            global $g_mandator_info;

            if (!isset($g_mandator_info['isys_mandator__dir_cache']) && !$g_mandator_info['isys_mandator__dir_cache']) {
                throw new Exception('Error: Cache directory in $g_mandator_info not set.');
            }

            self::$m_cache_dir = $g_mandator_info['isys_mandator__dir_cache'] . '/';
        }

        return isys_glob_get_temp_dir() . self::$m_cache_dir;
    }

    /**
     * Load cache.
     *
     * @static
     *
     * @param   isys_component_database $p_database
     *
     * @return  void
     */
    public static function initialize(isys_component_database $p_database)
    {
        if (!self::$m_initialized) {
            isys_component_signalcollection::get_instance()
                ->connect('system.shutdown', [
                    'isys_usersettings',
                    'shutdown'
                ]);

            self::$m_cachefile = 'settings.' . isys_application::instance()->session->get_user_id() . '.cache';

            if (!is_object(self::$m_dao)) {
                self::$m_dao = new isys_component_dao_user_settings($p_database);
            }

            $l_cache_dir = self::get_cache_dir();

            // Generate cache and load settings.
            if ($l_cache_dir) {
                try {
                    try {
                        if (!file_exists($l_cache_dir . self::$m_cachefile)) {
                            throw new InvalidCacheDataException();
                        }

                        self::load_cache($l_cache_dir);
                    } catch (InvalidCacheDataException $e) {
                        self::regenerate();
                    }
                } catch (Exception $e) {
                    if (isys_application::instance()->container->has('logger')) {
                        isys_application::instance()->container->get('logger')->error('User settings cache error: ' . $e->getMessage());
                    }

                    // Load settings from database instead of cache.
                    if (!is_array(self::$m_settings) || count(self::$m_settings) === 0) {
                        self::$m_settings = self::$m_dao->get_settings();
                    }
                }
            }

            self::$m_initialized = true;
        }
    }

    /**
     * (Re)generates cache. Loads the cache into self::$m_settings.
     *
     * @param  int $userId
     *
     * @throws  Exception
     * @return  array
     */
    public static function regenerate($userId = null)
    {
        try {
            if ($userId === null) {
                $userId = isys_application::instance()->container->get('session')->get_user_id();
            }

            self::$m_settings = self::$m_dao->get_settings();

            self::$m_cachefile = 'settings.' . $userId . '.cache';

            // Write settings cache.
            self::write(self::get_cache_dir() . self::$m_cachefile, self::$m_settings);
        } catch (Exception $e) {
            throw $e;
        }

        return self::$m_settings;
    }

    /**
     * Set a setting value.
     *
     * @static
     *
     * @param  string $p_key
     * @param  mixed  $p_value
     */
    public static function set($p_key, $p_value)
    {
        self::$m_changed = true;

        if (!isset(self::$m_settings[$p_key])) {
            self::$m_dao->set($p_key, $p_value)->apply_update();
        }

        self::$m_settings[$p_key] = $p_value;
    }
}
