<?php
/**
 * @property \modelUsers $model
 */
class users extends cmsFrontend {

    protected $useOptions = true;
    public $useSeoOptions = true;

    /**
     * Профиль текущего авторизованного пользователя
     * @var boolean
     */
    public $is_own_profile = false;

    /**
     * Просматриваемый профиль в дружбе с текущим пользователем
     * @var boolean
     */
    public $is_friend_profile = false;

    /**
     * Текущий пользователь подписан на просматриваемого
     * @var boolean
     */
    public $is_subscribe_profile = false;

    /**
     * Текущий просматриваемый профиль
     * @var array
     */
    public $profile = [];

    public $tabs = [];
    public $tabs_controllers = [];

    public function routeAction($action_name) {

        if (is_numeric($action_name)) {

            // $action_name это id пользователя
            $profile = $this->model->getUser($action_name, 'join_inviter');
            if (!$profile) {
                return cmsCore::error404();
            }

            if ($profile['slug'] !== $action_name) {
                return $this->redirectTo($this->name, $profile['slug'], $this->current_params, $this->cms_core->uri_query, 301);
            }

        } else {

            if ($this->isActionExists($action_name)) {
                return $action_name;
            }

            $profile = $this->model->getUserBySlug($action_name);
            // Не нашли профиль, значит это набор списка
            if (!$profile) {

                array_unshift($this->current_params, $action_name);

                return 'index';
            }
        }

        // разблокируем вызов экшенов, которым запрещено вызываться напрямую
        $this->lock_explicit_call = false;

        $this->setCurrentProfile($profile);

        if (!$this->cms_user->is_logged && $this->options['is_auth_only']) {
            return $this->redirectToLogin();
        }

        if ($this->options['is_themes_on']) {
            $this->cms_template->applyProfileStyle($this->profile);
        }

        $this->current_params = $this->cms_core->uri_params;

        // кешируем запись для получения ее в виджетах
        cmsModel::cacheResult('current_profile', $this->profile);

        // Нет параметров после названия экшена (/users/id) - значит
        // это главная страница профиля, первым параметром добавляем
        // сам профиль
        if (!$this->cms_core->uri_params) {

            $this->cms_template->addHead('<link rel="canonical" href="' . href_to_profile($profile, false, true) . '">');

            array_unshift($this->current_params, $this->profile);

            return 'profile';
        }

        // Ищем экшен внутри профиля
        if ($this->isActionExists('profile_' . $this->cms_core->uri_params[0])) {

            $this->cms_template->addHead('<link rel="canonical" href="' . href_to_profile($profile, [$this->cms_core->uri_params[0], $this->cms_core->uri_params[1] ?? null], true) . '">');

            $this->current_params[0] = $this->profile;

            return 'profile_' . $this->cms_core->uri_params[0];
        }

        // Если дошли сюда, значит это неизвестный экшен, возможно вкладка
        // от другого контроллера, тогда первым параметром добавляем
        // сам профиль
        array_unshift($this->current_params, $this->profile);

        return 'profile_tab';
    }

    public function setCurrentProfile($profile) {

        // Статус
        if ($this->options['is_status']) {
            $profile['status'] = $this->model->getUserStatus($profile['status_id']);
        }

        // Репутация
        $profile['is_can_vote_karma'] = $this->cms_user->is_logged &&
                cmsUser::isAllowed('users', 'vote_karma') &&
                ($this->cms_user->id != $profile['id']) &&
                $this->model->isUserCanVoteKarma($this->cms_user->id, $profile['id'], $this->options['karma_time']);

        $this->profile = $profile;

        $this->is_own_profile       = $this->cms_user->id == $profile['id'];
        $this->is_friend_profile    = $this->cms_user->isFriend($profile['id']);
        $this->is_subscribe_profile = $this->cms_user->isSubscribe($profile['id']);

        return $this;
    }

    public function getProfileMenu($profile) {

        static $menu = [];

        if ($menu !== []) {
            return $menu;
        }

        $menu[] = [
            'title'    => LANG_USERS_PROFILE_INDEX,
            'url'      => href_to_profile($profile),
            'url_mask' => href_to_profile($profile)
        ];

        if ($profile['is_deleted']) {
            return $menu;
        }

        // Доступность профиля для данного пользователя
        if (!$this->cms_user->isPrivacyAllowed($profile, 'users_profile_view')) {
            return $menu;
        }

        $this->tabs = $this->model->getUsersProfilesTabs(true, 'name');

        $this->tabs_controllers = ['users' => $this];

        if ($this->tabs) {
            foreach ($this->tabs as $tab) {

                // включен ли контроллер
                if (!$this->isControllerEnabled($tab['controller'])) {
                    continue;
                }

                // права доступа
                if (($tab['groups_view'] && !$this->cms_user->isInGroups($tab['groups_view'])) ||
                        ($tab['groups_hide'] && $this->cms_user->isInGroups($tab['groups_hide']))) {
                    continue;
                }

                // опция "показывать только владельцу профиля"
                // Админам показываем всегда
                if ($tab['show_only_owner'] && $profile['id'] != $this->cms_user->id && !$this->cms_user->is_admin) {
                    continue;
                }

                $default_tab_info = [
                    'title' => $tab['title'],
                    'url'   => href_to_profile($profile, [$tab['name']])
                ];

                if (empty($this->tabs_controllers[$tab['controller']])) {
                    $controller = cmsCore::getController($tab['controller'], $this->request);
                } else {
                    $controller = $this->tabs_controllers[$tab['controller']];
                }

                $tab_info = $controller->runHook('user_tab_info', [$profile, $tab['name']]);

                if ($tab_info === false) {
                    unset($this->tabs[$tab['name']]);
                    continue;
                } else if ($tab_info === true) {
                    $tab_info = $default_tab_info;
                } else {
                    $tab_info = array_merge($default_tab_info, $tab_info);
                }

                $menu[$tab['name']] = $tab_info;

                $this->tabs_controllers[$tab['controller']] = $controller;
            }
        }

        return $menu;
    }

    public function getProfileEditMenu($profile) {

        $menu = [];

        $menu[] = [
            'title' => LANG_USERS_EDIT_PROFILE_MAIN,
            'url'   => href_to_profile($profile, ['edit'])
        ];

        if ($this->cms_template->hasProfileThemesOptions() && $this->options['is_themes_on']) {

            $menu[] = [
                'title' => LANG_USERS_EDIT_PROFILE_THEME,
                'url'   => href_to_profile($profile, ['edit', 'theme'])
            ];
        }

        if (cmsEventsManager::getEventListeners('user_notify_types')) {

            $menu[] = [
                'title' => LANG_USERS_EDIT_PROFILE_NOTICES,
                'url'   => href_to_profile($profile, ['edit', 'notices'])
            ];
        }

        if (!empty($this->options['is_friends_on'])) {

            $menu[] = [
                'title' => LANG_USERS_EDIT_PROFILE_PRIVACY,
                'url'   => href_to_profile($profile, ['edit', 'privacy'])
            ];
        }

        if ($this->is_own_profile || (!$profile['is_admin'] && $this->cms_user->is_admin)) {

            $menu[] = [
                'title' => LANG_SECURITY,
                'url'   => href_to_profile($profile, ['edit', 'password'])
            ];

            $menu[] = [
                'title' => LANG_USERS_SESSIONS,
                'url'   => href_to_profile($profile, ['edit', 'sessions'])
            ];
        }

        list($menu, $profile) = cmsEventsManager::hook('profile_edit_menu', [$menu, $profile]);

        return $menu;
    }

    public function renderProfilesList($page_url, $dataset_name = false, $actions = false) {

        $page = $this->request->get('page', 1);
        $perpage = (empty($this->options['limit']) ? 15 : $this->options['limit']);

        // Получаем поля
        $content_model = cmsCore::getModel('content');
        $content_model->setTablePrefix('');
        $content_model->orderBy('ordering');
        $fields = $content_model->getContentFields('{users}');

        $this->model->filterEqual('is_locked', null);

        // Постраничный вывод
        $this->model->limitPage($page, $perpage);

        list($fields, $this->model) = cmsEventsManager::hook('profiles_list_filter', array($fields, $this->model));

        $filters = [];

        // проверяем запросы фильтрации по полям
        foreach ($fields as $name => $field) {

            if (!$field['is_in_filter']) {
                continue;
            }

            $field['handler']->setItem(['ctype_name' => 'users', 'id' => null])->setContext('filter');

            $fields[$name] = $field;

            if (!$this->request->has($name)) {
                continue;
            }

            $value = $this->request->get($name, false, $field['handler']->getDefaultVarType(true));
            if (!$value) {
                continue;
            }

            $value = $field['handler']->storeFilter($value);
            if (!$value) {
                continue;
            }

            if ($field['handler']->applyFilter($this->model, $value) !== false) {
                $filters[$name] = $value;
            }
        }

        // Фильтр по IP только для администраторов
        if($this->cms_user->is_admin && $this->request->has('ip')){
            $this->model->filterEqual('ip', $this->request->get('ip', ''));
        }

        // Получаем количество и список записей
        $total = $this->model->getUsersCount();

        if ($this->request->has('show_count')) {

            $hint = LANG_SHOW . ' ' . html_spellcount($total, LANG_USERS_SPELL, null, null, 0);

            return $this->cms_template->renderJSON([
                'count'       => $total,
                'filter_link' => false,
                'hint'        => $hint
            ]);
        }

        $profiles = $this->model->getUsers($actions);

        if ($this->request->isStandard()) {
            if (!$profiles && $page > 1) {
                return cmsCore::error404();
            }
        }

        $this->model->makeProfileFields($fields, $profiles, $this->cms_user);

        list($profiles, $fields) = cmsEventsManager::hook('profiles_before_list', [$profiles, $fields]);

        return $this->cms_template->renderInternal($this, 'list', [
            'page_url'     => $page_url,
            'fields'       => $fields,
            'filters'      => $filters,
            'page'         => $page,
            'perpage'      => $perpage,
            'total'        => $total,
            'profiles'     => $profiles,
            'dataset_name' => $dataset_name,
            'user'         => $this->cms_user
        ]);
    }

    public function getDatasets() {

        $datasets = [];

        // Все (новые)
        $datasets[''] = [
            'name'  => '',
            'title' => LANG_USERS_DS_LATEST,
            'filter' => function ($model, $dset) {
                return $model->orderBy('i.date_reg', 'desc');
            }
        ];

        // Онлайн
        if ($this->options['is_ds_online']) {
            $datasets['online'] = [
                'name'   => 'online',
                'title'  => LANG_USERS_DS_ONLINE,
                'filter' => function ($model, $dset) {
                    $model->orderBy('i.date_log', 'desc');
                    return $model->joinSessionsOnline('i')->filterOnlineUsers();
                }
            ];
        }

        // Рейтинг
        if ($this->options['is_ds_rating']) {
            $datasets['rating'] = [
                'name'  => 'rating',
                'title' => LANG_USERS_DS_RATED,
                'filter' => function ($model, $dset) {
                    return $model->orderByList([
                        ['by' => 'karma', 'to' => 'desc'],
                        ['by' => 'rating', 'to' => 'desc']
                    ]);
                }
            ];
        }

        // Популярные
        if ($this->options['is_ds_popular']) {
            $datasets['popular'] = [
                'name'   => 'popular',
                'title'  => LANG_USERS_DS_POPULAR,
                'filter' => function ($model, $dset) {
                    return $model->orderBy('i.friends_count', 'desc');
                }
            ];
        }

        // Группы
        $f_groups = $this->model->getFilteredGroups();

        if ($f_groups) {
            foreach ($f_groups as $group) {
                $datasets[$group['name']] = [
                    'name'   => $group['name'],
                    'title'  => $group['title'],
                    'filter' => function ($model, $dset) {
                        $model->orderBy('i.date_reg', 'desc');
                        return $model->filterGroupByName($dset['name']);
                    }
                ];
            }
        }

        return cmsEventsManager::hook('profiles_datasets', $datasets);
    }

    public function logoutLockedUser($user) {

        $now        = time();
        $lock_until = !empty($user['lock_until']) ? strtotime($user['lock_until']) : false;

        if ($lock_until && ($lock_until <= $now)) {

            $this->model->unlockUser($user['id']);

            return $user;
        }

        $notice_text = [sprintf(LANG_USERS_LOCKED_NOTICE)];

        if ($user['lock_until']) {
            $notice_text[] = sprintf(LANG_USERS_LOCKED_NOTICE_UNTIL, html_date($user['lock_until']));
        }

        if ($user['lock_reason']) {
            $notice_text[] = sprintf(LANG_USERS_LOCKED_NOTICE_REASON, $user['lock_reason']);
        }

        if ($user['lock_reason']) {
            $this->model->update('{users}', $user['id'], [
                'ip' => null
            ], true);
        }

        cmsUser::addSessionMessage(implode('<br>', $notice_text), 'error');

        cmsUser::logout();

        return [];
    }

    public function listIsAllowed() {

        if(empty($this->options['list_allowed'])){
            return true;
        }

        return $this->cms_user->isInGroups($this->options['list_allowed']);

    }

    public function isSlugAllowed($value) {

        if ($this->cms_user->is_admin || !isset($this->options['restricted_slugs'])) { return true; }

        return !string_in_mask_list($value, $this->options['restricted_slugs']);
    }

    public function errorContext() {

        if ($this->request->isInternal()) {
            return false;
        }

        return cmsCore::error404();
    }

}
