<?php

/**
 * ======================================================================
 * LICENSE: This file is subject to the terms and conditions defined in *
 * file 'license.txt', which is part of this source code package.       *
 * ======================================================================
 */

use Vectorface\Whip\Whip;

/**
 * AAM core service
 *
 * @package AAM
 * @version 7.0.0
 */
class AAM_Service_Core
{

    use AAM_Service_BaseTrait;

    /**
     * ConfigPress DB option
     *
     * @version 7.0.0
     */
    const DB_OPTION = 'aam_configpress';

    /**
     * Default configurations
     *
     * @version 7.0.3
     */
    const DEFAULT_CONFIG = [
        'core.settings.ui.tips'                    => true,
        'core.settings.multi_access_levels'        => false,
        'core.settings.ui.render_access_metabox'   => false,
        'core.settings.xmlrpc_enabled'             => true,
        'core.settings.restful_enabled'            => true,
        'core.settings.multisite.members_only'     => false,
        'core.settings.multisite.sync'             => false,
        'core.settings.merge.preference'           => 'deny',
        'core.settings.multisite.ignore_resources' => [
            AAM_Framework_Type_Resource::POST,
            AAM_Framework_Type_Resource::TERM
        ]
    ];

    /**
     * Collection of capabilities responsible for API password management
     *
     * @version 7.0.0
     */
    const APP_PASSWORD_CAPS = [
        'create_app_password',
        'list_app_passwords',
        'read_app_password',
        'edit_app_password',
        'delete_app_passwords',
        'delete_app_password'
    ];

    /**
     * Constructor
     *
     * @access protected
     * @return void
     *
     * @version 7.0.4
     */
    protected function __construct()
    {
        add_filter('aam_get_config_filter', function($result, $key) {
            if (empty($result) && array_key_exists($key, self::DEFAULT_CONFIG)) {
                $result = self::DEFAULT_CONFIG[$key];
            }

            return $result;
        }, 10, 2);

        // Hook into AAM config initialization and enrich it with ConfigPress
        // settings
        add_filter('aam_init_config_filter', function($configs) {
            return $this->_aam_initialize_config($configs);
        });

        // Control user's status
        add_action('set_current_user', function() {
            $this->_control_user_account();
        });

        // Bootstrap RESTful API
        AAM_Restful_Mu::bootstrap();
        AAM_Restful_Roles::bootstrap();
        AAM_Restful_Users::bootstrap();
        AAM_Restful_Configs::bootstrap();
        AAM_Restful_Settings::bootstrap();
        AAM_Restful_BackwardCompatibility::bootstrap();

        add_action('init', function() {
            $this->initialize_hooks();
        }, PHP_INT_MAX);
    }

    /**
     * Initialize service hooks
     *
     * @return void
     * @access protected
     *
     * @version 7.0.4
     */
    protected function initialize_hooks()
    {
        // Ensuring safely of transactions
        add_filter('gettext_advanced-access-manager', function($translation) {
            return esc_html($translation);
        });

        if (is_admin()) {
            $metabox_enabled = AAM::api()->config->get(
                'core.settings.ui.render_access_metabox'
            );

            if ($metabox_enabled) {
                add_action('edit_user_profile', function($user) {
                    if (current_user_can('aam_manager')) {
                        $this->_render_access_widget($user);
                    }
                });
            }

            // Hook that initialize the AAM UI part of the service
            add_action('aam_initialize_ui_action', function () {
                AAM_Backend_Feature_Settings_Service::register();
                AAM_Backend_Feature_Settings_Core::register();
                AAM_Backend_Feature_Settings_Content::register();
                AAM_Backend_Feature_Settings_ConfigPress::register();
                AAM_Backend_Feature_Settings_Manager::register();
            }, 1);

            if (is_multisite()) {
                add_action('aam_initialize_ui_action', function () {
                    AAM_Backend_Feature_Settings_Multisite::register();
                });
            }
        }

        // Allow third-party plugins to use AAM user IP detection
        add_filter('aam_get_user_ip_address_filter', function() {
            $whip = new Whip();

            return $whip->getValidIpAddress();
        });

        // Handle access denied
        add_action('aam_deny_access_action', function() {
            AAM::api()->redirect->do_access_denied_redirect();
        });

        // Add toolbar "Manage Access" item
        add_action('admin_bar_menu', function($wp_admin_bar) {
            if (current_user_can('aam_manager')) {
                $wp_admin_bar->add_menu(
                    array(
                        'parent' => 'site-name',
                        'id'     => 'aam',
                        'title'  => __('Manager Access', 'advanced-access-manager'),
                        'href'   => admin_url('admin.php?page=aam'),
                    )
                );
            }
        }, 999);

        // Add "Manage Access" to all sites if multisite network
        if (is_multisite()) {
            add_action('admin_bar_menu', function($wp_admin_bar) {
                $blog_count = 0;

                if (is_object($wp_admin_bar->user)) {
                    if (is_iterable($wp_admin_bar->user->blogs)) {
                        $blog_count = count($wp_admin_bar->user->blogs);
                    }
                }

                if ($blog_count > 0 || current_user_can('manage_network')) {
                    foreach((array) $wp_admin_bar->user->blogs as $blog) {
                        switch_to_blog($blog->userblog_id);

                        $menu_id = 'blog-' . $blog->userblog_id;

                        if (current_user_can('aam_manager')) {
                            $wp_admin_bar->add_menu(
                                array(
                                    'parent' => $menu_id,
                                    'id'     => $menu_id . '-aam',
                                    'title'  => __('Manage Access', 'advanced-access-manager'),
                                    'href'   => admin_url('admin.php?page=aam'),
                                )
                            );
                        }

                        restore_current_blog();
                    }
                }
            }, 999);

            add_action('wp', function() {
                $this->_control_multisite_members_only();
            }, 999);

            // Control access controls & configurations sync
            $this->_control_multisite_settings_sync();
        }

        // Check if user has ability to perform certain task based on provided
        // capability and meta data
        add_filter('map_meta_cap', function($caps, $_, $user_id) {
            return $this->_map_meta_cap($caps, $user_id);
        }, 999, 3);

        // User authentication control
        add_filter('wp_authenticate_user', function($result) {
            return $this->_authenticate_user($result);
        }, 1);

        // Disable XML-RPC if needed
        add_filter('xmlrpc_enabled', function($enabled) {
            if (AAM::api()->config->get(
                'core.settings.xmlrpc_enabled') === false
            ) {
                $enabled = false;
            }

            return $enabled;
        }, PHP_INT_MAX);

        // Disable RESTful API if needed
        add_filter('rest_authentication_errors', function ($response) {
            if (!current_user_can('aam_manager')
                && !is_wp_error($response)
                && !AAM::api()->config->get('core.settings.restful_enabled')
            ) {
                $response = new WP_Error(
                    'rest_access_disabled',
                    __('RESTful API is disabled', 'advanced-access-manager'),
                    array('status' => 403)
                );
            }

            return $response;
        }, PHP_INT_MAX);

        // Control admin notifications
        add_action(
            'admin_notices',
            function() { $this->_control_admin_notices(); },
            -1
        );
        add_action(
            'network_admin_notices',
            function() { $this->_control_admin_notices(); },
            -1
        );
        add_action(
            'user_admin_notices',
            function() { $this->_control_admin_notices(); }, -1
        );

        // Screen options & contextual help hooks
        add_filter('screen_options_show_screen', function() {
            return $this->_control_screen_options();
        });
        add_action('in_admin_header', function() {
            $this->_control_help_tabs();
        });

        // Permalink manager
        add_filter('get_sample_permalink_html', function ($html) {
            return $this->_control_permalink_html($html);
        });

        // Control the ability to manage application password
        add_filter(
            'wp_is_application_passwords_available_for_user',
            function($response, $user) {
                return $this->_is_app_passwords_available_for_user(
                    $response, $user
                );
            }, 10, 2
        );

        // Control access to the backend area
        $this->_control_admin_area_access();
        $this->_control_admin_toolbar();

        // Run upgrades if available
        AAM_Core_Migration::run();
    }

    /**
     * Export all AAM settings & configurations
     *
     * @return array
     * @access public
     *
     * @version 7.0.0
     */
    public function export()
    {
        $db     = AAM::api()->db;
        $result = [
            'version'   => AAM_VERSION,
            'plugin'    => 'advanced-access-manager',
            'timestamp' => (new DateTime('now', new DateTimeZone('UTC')))->format('U'),
            'dataset'   => [
                'settings'    => $db->read(AAM_Framework_Service_Settings::DB_OPTION, []),
                'configs'     => $db->read(AAM_Framework_Utility_Config::DB_OPTION, []),
                'configpress' => $db->read(self::DB_OPTION, ''),
                'roles'       => $db->read(wp_roles()->role_key, []),
                'policies'    => []
            ]
        ];

        // Get list of all JSON policies
        $policies = get_posts([
            'post_status'      => [ 'publish', 'draft', 'pending', 'private' ],
            'nopaging'         => true,
            'suppress_filters' => true,
            'post_type'        => AAM_Framework_Service_Policies::CPT
        ]);

        foreach($policies as $policy) {
            array_push($result['dataset']['policies'], [
                'id'      => $policy->ID,
                'slug'    => $policy->post_name,
                'content' => $policy->post_content,
                'status'  => $policy->post_status,
                'title'   => $policy->post_title,
                'excerpt' => $policy->post_excerpt
            ]);
        }

        return $result;
    }

    /**
     * Import settings
     *
     * @param array $dataset
     *
     * @return bool
     * @access public
     *
     * @version 7.0.6
     */
    public function import($dataset)
    {
        // Import data in very specific order
        $policy_map = [];

        if (array_key_exists('policies', $dataset)) {
            foreach($dataset['policies'] as $policy) {
                $insert = true;

                if (!empty($policy['slug'])) {
                    $existing = AAM::api()->misc->get_post_by_slug(
                        $policy['slug'],
                        AAM_Framework_Service_Policies::CPT
                    );

                    $insert = is_a($existing, WP_Post::class) ? false : true;
                }

                if ($insert) {
                    $policy_map[$policy['id']] = wp_insert_post([
                        'post_content' => $policy['content'],
                        'post_type'    => AAM_Framework_Service_Policies::CPT,
                        'post_status'  => $policy['status'],
                        'post_title'   => $policy['title'],
                        'post_excerpt' => $policy['excerpt']
                    ]);
                } else {
                    $policy_map[$policy['id']] = $existing->ID;

                    // Update existing policy with new imported content
                    wp_update_post([
                        'ID' => $existing->ID,
                        'post_content' => $policy['content'],
                        'post_title'   => $policy['title'],
                        'post_excerpt' => $policy['excerpt']
                    ]);
                }
            }
        }

        // Import raw data sets
        $db = AAM::api()->db;

        if (array_key_exists('roles', $dataset)) {
            $db->write(wp_roles()->role_key, $dataset['roles']);
        }

        if (array_key_exists('configpress', $dataset)) {
            $db->write(self::DB_OPTION, $dataset['configpress']);
        }

        if (array_key_exists('configs', $dataset)) {
            $db->write(AAM_Framework_Utility_Config::DB_OPTION, $dataset['configs']);
        }

        if (array_key_exists('settings', $dataset)) {
            // If policy map is not empty, replace all old policy ids with new
            if (!empty($policy_map)) {
                $settings = $this->_replace_policy_ids(
                    $dataset['settings'], $policy_map
                );
            } else {
                $settings = $dataset['settings'];
            }

            $db->write(AAM_Framework_Service_Settings::DB_OPTION, $settings);
        }

        return true;
    }

    /**
     * Reset AAM
     *
     * @return bool
     * @access public
     *
     * @version 7.0.0
     */
    public function reset()
    {
        global $wpdb;

        // Clear all configurations & settings

        $options = array(
            AAM_Framework_Service_Settings::DB_OPTION,
            AAM_Core_Migration::DB_OPTION,
            AAM_Framework_Utility_Config::DB_OPTION,
            AAM_Framework_Utility_Cache::DB_OPTION,
            AAM_Service_Core::DB_OPTION,
            AAM_Service_SecurityAudit::DB_OPTION,
            AAM_Service_SecurityAudit::DB_SCOPE_OPTION
        );

        foreach($options as $option) {
            AAM::api()->db->delete($option);
        }

        // Delete all legacy options
        $query  = "DELETE FROM {$wpdb->options} WHERE (`option_name` LIKE %s) AND ";
        $query .= "(`option_name` NOT IN ('aam_addons', 'aam_migrations'))";
        $wpdb->query($wpdb->prepare($query, 'aam%'));

        $wpdb->query($wpdb->prepare(
            "DELETE FROM {$wpdb->postmeta} WHERE `meta_key` LIKE %s", 'aam-%'
        ));

        $wpdb->query($wpdb->prepare(
            "DELETE FROM {$wpdb->usermeta} WHERE `meta_key` LIKE %s", 'aam%'
        ));

        $wpdb->query($wpdb->prepare(
            "DELETE FROM {$wpdb->usermeta} WHERE `meta_key` LIKE %s",
            $wpdb->get_blog_prefix() . 'aam%'
        ));

        // Trigger the action to inform other services to clean-up the options
        do_action('aam_reset_action', $options);

        return true;
    }

    /**
     * Replace old policy ids with new
     *
     * @param array $settings
     * @param array $policy_map
     *
     * @return array
     * @access private
     *
     * @version 7.0.0
     */
    private function _replace_policy_ids($settings, $policy_map)
    {
        foreach($settings as $key => $data) {
            if ($key === 'policy' && is_array($data)) {
                foreach($data as $policy_id => $perm) {
                    if (isset($policy_map[$policy_id])) {
                        $settings[$key][$policy_map[$policy_id]] = $perm;
                    }
                }
            } elseif (is_array($data)) {
                $settings[$key] = $this->_replace_policy_ids($data, $policy_map);
            }
        }

        return $settings;
    }

    /**
     * Manage notifications visibility
     *
     * @return void
     * @access private
     *
     * @version 7.0.0
     */
    private function _control_admin_notices()
    {
        if (!$this->_current_user_can('aam_show_admin_notices')) {
            remove_all_actions('admin_notices');
            remove_all_actions('network_admin_notices');
            remove_all_actions('user_admin_notices');
        }
    }

    /**
     * Control if user has access to the Screen Options
     *
     * @return bool
     * @access private
     *
     * @version 7.0.0
     */
    private function _control_screen_options()
    {
        if (is_admin() && isset($_GET['page']) && $_GET['page'] === 'aam') {
            $result = false;
        } else {
            $result = $this->_current_user_can('aam_show_screen_options');
        }

        return $result;
    }

    /**
     * Control Help Tabs
     *
     * @return void
     * @access private
     *
     * @version 7.0.0
     */
    private function _control_help_tabs()
    {
        $screen = get_current_screen();

        if (!$this->_current_user_can('aam_show_help_tabs')
            && is_a($screen, WP_Screen::class)
        ) {
            get_current_screen()->remove_help_tabs();
        }
    }

    /**
     * Control permalink editing ability
     *
     * @param string $html
     *
     * @return string
     * @access private
     *
     * @version 7.0.0
     */
    private function _control_permalink_html($html)
    {
        if (!$this->_current_user_can('aam_edit_permalink')) {
            $html = '';
        }

        return $html;
    }

    /**
     * Control access to the admin area
     *
     * @return void
     * @access private
     *
     * @version 7.0.1
     */
    private function _control_admin_area_access()
    {
        if (is_user_logged_in() && is_admin()) {
            // Check if user is allowed to see backend
            if (!$this->_current_user_can('aam_access_dashboard')) {
                // If this is the AJAX call, still allow it because it will break
                // a lot of frontend stuff that depends on it
                if (!defined('DOING_AJAX')) {
                    AAM::api()->redirect->do_access_denied_redirect();
                }
            }
        }
    }

    /**
     * Control if user can see admin toolbar
     *
     * @return void
     * @access private
     *
     * @version 7.0.0
     */
    private function _control_admin_toolbar()
    {
        if (is_user_logged_in() && !$this->_current_user_can('aam_show_toolbar')) {
            add_filter('show_admin_bar', '__return_false', PHP_INT_MAX);
        }
    }

    /**
     * Check if current user has a capability
     *
     * This method checks if capability is actually existing first and then check
     * if user has it assigned
     *
     * @param string $cap
     *
     * @return bool
     * @access private
     *
     * @version 7.0.0
     */
    private function _current_user_can($cap)
    {
        return !AAM::api()->caps->exists($cap) || current_user_can($cap);
    }

    /**
     * Control if user has access to current site
     *
     * @return void
     * @access private
     *
     * @version 7.0.0
     */
    private function _control_multisite_members_only()
    {
        // Check if the non-member access restriction is on
        if (AAM::api()->config->get('core.settings.multisite.members_only')
            && !is_user_member_of_blog()
        ) {
            AAM::api()->redirect->do_access_denied_redirect();
        }
    }

    /**
     * Controlling how access controls & settings are sync
     *
     * @return void
     * @access private
     *
     * @version 7.0.3
     */
    private function _control_multisite_settings_sync()
    {
        $enabled = AAM::api()->config->get('core.settings.multisite.sync');

        if ($enabled && get_current_blog_id() !== get_main_site_id()) {
            // Sync roles & capabilities. Note! We only sync roles & caps and do not
            // bother syncing user caps
            add_filter('pre_option_' . wp_roles()->role_key, function() {
                $main_site_roles = new WP_Roles(get_main_site_id());

                return $main_site_roles->roles;
            });

            add_filter('aam_init_settings_filter', function($settings) {
                $base = AAM::api()->db->read(
                    AAM_Framework_Service_Settings::DB_OPTION,
                    [],
                    get_main_site_id()
                );

                $response = [];

                // Now, let's merge main site settings with settings for a current
                // blog
                $levels = array_unique(array_merge(
                    is_array($settings) ? array_keys($settings) : [],
                    is_array($base) ? array_keys($base) : []
                ));

                foreach ($levels as $level) {
                    if (in_array($level, [
                        AAM_Framework_Type_AccessLevel::DEFAULT,
                        AAM_Framework_Type_AccessLevel::VISITOR
                    ])) {
                        $response[$level] = $this->_merge_settings(
                            isset($settings[$level]) ? $settings[$level] : [],
                            isset($base[$level]) ? $base[$level] : []
                        );
                    } else {
                        $response[$level] = $this->_merge_identity_settings(
                            isset($settings[$level]) ? $settings[$level] : [],
                            isset($base[$level]) ? $base[$level] : []
                        );
                    }
                }

                return $response;
            });
        }
    }

    /**
     * Merge to set of settings into one
     *
     * @param array $settings
     * @param array $base_settings
     *
     * @return array
     * @access private
     *
     * @version 7.0.3
     */
    private function _merge_settings($settings, $base_settings)
    {
        $response = [];
        $ignore   = AAM::api()->config->get(
            'core.settings.multisite.ignore_resources'
        );

        // Get unique list of resource types
        $types = array_unique(array_merge(
            is_array($settings) ? array_keys($settings) : [],
            is_array($base_settings) ? array_keys($base_settings) : []
        ));

        foreach($types as $type) {
            if (!in_array($type, $ignore)) {
                $response[$type] = array_replace(
                    isset($base_settings[$type]) ? $base_settings[$type] : [],
                    isset($settings[$type]) ? $settings[$type] : []
                );
            }
        }

        return $response;
    }

    /**
     * Merge role or user settings
     *
     * @param array $settings
     * @param array $base_settings
     *
     * @return array
     * @access private
     *
     * @version 7.0.3
     */
    private function _merge_identity_settings($settings, $base_settings)
    {
        $response = [];

        // Get unique list of identity ids
        $ids = array_unique(array_merge(
            is_array($settings) ? array_keys($settings) : [],
            is_array($base_settings) ? array_keys($base_settings) : []
        ));

        foreach($ids as $id) {
            $response[$id] = $this->_merge_settings(
                isset($settings[$id]) ? $settings[$id] : [],
                isset($base_settings[$id]) ? $base_settings[$id] : []
            );
        }

        return $response;
    }

    /**
     * Initialize configurations by adding ConfigPress settings
     *
     * @param array $configs
     *
     * @return array
     * @access private
     *
     * @version 7.0.3
     */
    private function _aam_initialize_config($configs)
    {
        $response = $this->_enhance_with_configpress($configs);

        if (is_multisite() && get_current_blog_id() !== get_main_site_id()) {
            $base = $this->_enhance_with_configpress(AAM::api()->db->read(
                AAM_Framework_Utility_Config::DB_OPTION,
                [],
                get_main_site_id()
            ), get_main_site_id());

            $response = array_replace($base, $response);
        }

        return $response;
    }

    /**
     * Enhance configuration with ConfigPress
     *
     * @param array $configs
     *
     * @return array
     * @access private
     *
     * @version 7.0.3
     */
    private function _enhance_with_configpress($configs, $blog_id = null)
    {
        $configpress = AAM::api()->db->read(self::DB_OPTION, null, $blog_id);

        if (!empty($configpress) && is_string($configpress)) {
            $result = parse_ini_string($configpress, true, INI_SCANNER_TYPED);

            if ($result !== false) { // Clear error
                // If we have "aam" key, then AAM ConfigPress is properly formatted
                // and we take all the values from this section.
                // Otherwise - assume that user forgot to add the "[aam]" section
                if (array_key_exists('aam', $result)) {
                    $configs = array_merge($configs, $result['aam']);
                } else {
                    $configs = array_merge($configs, $result);
                }
            }
        }

        return $configs;
    }

    /**
     * Determine if given user is allowed to manage application passwords
     *
     * @param bool    $response
     * @param WP_User $user
     *
     * @return bool
     * @access private
     *
     * @version 7.0.0
     */
    private function _is_app_passwords_available_for_user($response, $user)
    {
        if (AAM::api()->caps->exists('aam_manage_application_passwords')) {
            $response = user_can($user, 'aam_manage_application_passwords');
        }

        return $response;
    }

    /**
     * Render "Access Manager" widget on the user/profile edit screen
     *
     * @param WP_User $user
     *
     * @return void
     * @access public
     *
     * @version 7.0.0
     */
    private function _render_access_widget($user)
    {
        echo AAM_Backend_View::get_instance()->renderUserMetabox($user);
    }

    /**
     * Check user capability
     *
     * This is a hack function that add additional layout on top of WordPress
     * core functionality. Based on the capability passed in the $args array as
     * "0" element, it performs additional check on user's capability to manage
     * post, users etc.
     *
     * @param array $caps
     * @param int   $user_id
     *
     * @return array
     * @access public
     *
     * @version 7.0.0
     */
    private function _map_meta_cap($caps, $user_id)
    {
        // Mutate any AAM specific capability if it does not exist
        foreach ((array) $caps as $i => $capability) {
            if (is_string($capability) && (strpos($capability, 'aam_') === 0)) {
                if (!AAM::api()->capabilities->exists($capability)) {
                    $caps[$i] = AAM::api()->config->get(
                        'page.capability',
                        'administrator'
                    );
                }
            } elseif (in_array($capability, self::APP_PASSWORD_CAPS, true)) {
                if (!$this->_is_app_passwords_available_for_user(true, $user_id)) {
                    array_push($caps, 'do_not_allow');
                }
            }
        }

        return $caps;
    }

    /**
     * Validate user status
     *
     * Check if user is locked or not
     *
     * @param WP_Error $user
     *
     * @return WP_Error|WP_User
     * @access public
     *
     * @version 7.0.0
     */
    private function _authenticate_user($result)
    {
        // Check if user is blocked
        if (is_a($result, 'WP_User')) {
            $user = AAM::api()->users->get_user($result);

            // Step #1. Verify that user is active
            if (!$user->is_user_active()) {
                $result = new WP_Error(
                    'inactive_user',
                    '[ERROR]: User is inactive. Contact the administrator.'
                );
            }

            // Step #2. Verify that user is not expired
            if ($user->is_user_access_expired()) {
                $result = new WP_Error(
                    'inactive_user',
                    '[ERROR]: User access is expired. Contact the administrator.'
                );
            }
        }

        return $result;
    }

    /**
     * Verify user status and act accordingly if user is no longer active or
     * expired
     *
     * @return void
     * @access public
     *
     * @version 7.0.0
     */
    private function _control_user_account()
    {
        $user = AAM::api()->users->get_user(get_current_user_id());

        if (!is_null($user)) {
            // If user status is inactive - immediately logout user
            if ($user->is_user_active() === false) {
                wp_logout();
                exit;
            } elseif ($user->is_user_access_expired()) {
                // Trigger specified action
                switch ($user->expiration_trigger['type']) {
                    case 'change-role':
                    case 'change_role':
                        $user->set_role($user->expiration_trigger['to_role']);
                        $user->reset('expiration');
                        break;

                    case 'delete': // For compatibility purposes
                    case 'lock':
                        $user->update(['status' => $user::STATUS_INACTIVE]);
                        $user->reset('expiration');
                        // And logout immediately

                    case 'logout':
                        wp_logout();
                        exit;
                        break;

                    default:
                        break;
                }
            }
        }
    }

}