<?php
/**
 * @property \modelPhotos $model
 */
class actionPhotosView extends cmsAction {

    private $related_title = '';

    protected $extended_langs = ['content'];

    public function run($id = false){

        // редиректим со старых адресов
        if ($id) {

            $photo = $this->model->getPhoto($id);

            if (!$photo || !$photo['slug']) {
                return cmsCore::error404();
            }

            return $this->redirect(href_to('photos', $photo['slug'] . '.html'), 301);
        }

        $slug = $this->request->get('slug', '');
        if (!$slug) {
            return cmsCore::error404();
        }

        $photo = $this->model->getPhoto($slug);
        if (!$photo) {
            return cmsCore::error404();
        }

        $album = $this->model->getAlbum($photo['album_id']);
        if (!$album) {
            return cmsCore::error404();
        }

        $ctype = $album['ctype'];
        unset($album['ctype']);

        list($photo, $album, $ctype) = cmsEventsManager::hook('photos_before_item', [$photo, $album, $ctype]);

        // Проверяем прохождение модерации
        $is_moderator = $this->controller_moderation->userIsContentModerator($ctype['name'], $this->cms_user->id, $album);

        // на модерации
        if (!$album['is_approved']) {

            $item_view_notice = $album['is_draft'] ? LANG_CONTENT_DRAFT_NOTICE : LANG_MODERATION_NOTICE;

            if (!$is_moderator && $this->cms_user->id != $album['user_id']) {
                return cmsCore::errorForbidden($item_view_notice, true);
            }

            cmsUser::addSessionMessage($item_view_notice, 'info');
        }

        // Проверяем приватность альбома
        if ($album['is_private'] == 1) { // доступ только друзьям

            $is_friend           = $this->cms_user->isFriend($album['user_id']);
            $is_can_view_private = cmsUser::isAllowed($ctype['name'], 'view_all');

            if (!$is_friend && !$is_can_view_private && !$is_moderator) {

                // если в настройках указано скрывать, 404
                if (empty($ctype['options']['privacy_type']) || $ctype['options']['privacy_type'] == 'hide') {
                    return cmsCore::error404();
                }

                // иначе пишем, к кому в друзья нужно проситься
                cmsUser::addSessionMessage(sprintf(
                        LANG_CONTENT_PRIVATE_FRIEND_INFO,
                        (!empty($ctype['labels']['one']) ? $ctype['labels']['one'] : LANG_PAGE),
                        href_to_profile($album['user']),
                        htmlspecialchars($album['user']['nickname'])
                ), 'info');

                return $this->redirect(href_to($ctype['name']));
            }
        }

        // Проверяем приватность фото
        if ($photo['is_private'] == 1) { // доступ только друзьям

            $is_friend           = $this->cms_user->isFriend($photo['user_id']);
            $is_can_view_private = cmsUser::isAllowed($ctype['name'], 'view_all');

            if (!$is_friend && !$is_can_view_private && !$is_moderator) {

                // иначе пишем, к кому в друзья нужно проситься
                cmsUser::addSessionMessage(sprintf(
                        LANG_CONTENT_PRIVATE_FRIEND_INFO,
                        LANG_PHOTOS_WP_ITEM,
                        href_to_profile($photo['user']),
                        htmlspecialchars($photo['user']['nickname'])
                ), 'info');

                return $this->redirect(href_to($ctype['name'], $album['slug'] . '.html'));
            }
        }

        // Проверяем ограничения доступа из других контроллеров
        if ($album['is_parent_hidden'] || $album['is_private']) {

            $is_parent_viewable_result = cmsEventsManager::hook('content_view_hidden', [
                'viewable'     => true,
                'item'         => $album,
                'is_moderator' => $is_moderator,
                'ctype'        => $ctype
            ]);

            if (!$is_parent_viewable_result['viewable']) {

                if (isset($is_parent_viewable_result['access_text'])) {

                    cmsUser::addSessionMessage($is_parent_viewable_result['access_text'], 'error');

                    if (isset($is_parent_viewable_result['access_redirect_url'])) {
                        return $this->redirect($is_parent_viewable_result['access_redirect_url']);
                    } else {
                        return $this->redirect(href_to($ctype['name']));
                    }
                }

                return $this->redirectToLogin();
            }
        }

        if ($this->cms_user->id != $photo['user_id']) {
            $this->model->incrementCounter($photo['id']);
        }

        $is_can_set_cover = (cmsUser::isAllowed($ctype['name'], 'edit', 'all') ||
                (cmsUser::isAllowed($ctype['name'], 'edit', 'own') && $album['user_id'] == $this->cms_user->id));

        $is_can_edit = (cmsUser::isAllowed($ctype['name'], 'edit', 'all') ||
                (cmsUser::isAllowed($ctype['name'], 'edit', 'own') && $album['user_id'] == $this->cms_user->id) ||
                ($photo['user_id'] == $this->cms_user->id));

        $is_can_delete = (cmsUser::isAllowed($ctype['name'], 'delete', 'all') ||
                (cmsUser::isAllowed($ctype['name'], 'delete', 'own') && $album['user_id'] == $this->cms_user->id) ||
                ($photo['user_id'] == $this->cms_user->id));

        $downloads           = $this->getDownloadImages($photo);
        $available_downloads = array_filter($downloads, function ($item) {
            return !empty($item['link']);
        });
        $full_size_img_preset = '';
        if ($available_downloads) {

            $download_photo_sizes = [];

            foreach ($available_downloads as $preset => $data) {
                $download_photo_sizes[$preset] = $photo['sizes'][$preset];
            }

            $full_size_img_preset = $this->getMaxSizePresetName($download_photo_sizes);
        }

        $ordering = $this->request->get('ordering', $this->options['ordering']);
        $orderto  = $this->request->get('orderto', $this->options['orderto']);

        if (!in_array($ordering, array_keys(modelPhotos::getOrderList()))) {
            return cmsCore::error404();
        }

        if (!in_array($orderto, ['asc', 'desc'])) {
            return cmsCore::error404();
        }

        $photos_url_params = [];
        if ($ordering != $this->options['ordering']) {
            $photos_url_params['ordering'] = $ordering;
        }
        if ($orderto != $this->options['orderto']) {
            $photos_url_params['orderto'] = $orderto;
        }
        if ($photos_url_params) {
            $photos_url_params = http_build_query($photos_url_params);
        }

        // Навигация
        list($prev_photo, $next_photo) = $this->getNavPhotos($photo, $ordering, $orderto);

        $tpl    = 'view';
        $preset = $this->getBigPreset($photo['sizes']);

        if ($this->request->isAjax()) {

            $tpl = 'view_photo_container';
            if ($full_size_img_preset) {
                $preset = $full_size_img_preset;
            }
        }

        cmsModel::cacheResult('current_photo_item', [$album, $photo]);

        return $this->cms_template->render($tpl, [
            'photos_url_params' => $photos_url_params,
            'row_height'        => $this->getRowHeight((!empty($this->options['preset_related']) ? 'preset_related' : 'preset_small')),
            'next_photo'        => $next_photo,
            'prev_photo'        => $prev_photo,
            'hide_info_block'   => !empty($this->options['hide_photo_item_info']),
            'downloads'         => !empty($this->options['allow_download']) ? $downloads : [],
            'is_can_set_cover'  => $is_can_set_cover,
            'is_can_edit'       => $is_can_edit,
            'is_can_delete'     => $is_can_delete,
            'user'              => $this->cms_user,
            'preset'            => $preset,
            'preset_small'      => (!empty($this->options['preset_related']) ? $this->options['preset_related'] : $this->options['preset_small']),
            'photo'             => $photo,
            'photos'            => $this->getRelatedPhoto($photo),
            'related_title'     => $this->related_title,
            'album'             => $album,
            'ctype'             => $ctype,
            'photo_details'     => $this->buildPhotoDetails($photo, $album, $ctype),
            'hooks_html'        => cmsEventsManager::hookAll('photos_item_html', $photo),
            'full_size_img'     => ($full_size_img_preset ? $available_downloads[$full_size_img_preset]['image'] : '')
        ]);
    }

    private function getNavPhotos($photo, $ordering, $orderto) {

        switch ($orderto) {
            case 'asc':

                $prev_photo = $this->model->filterEqual('album_id', $photo['album_id'])->
                        getNextPhoto($photo, $ordering, 'desc');
                $next_photo = $this->model->filterEqual('album_id', $photo['album_id'])->
                        getPrevPhoto($photo, $ordering, $orderto);
                break;

            case 'desc':

                $next_photo = $this->model->filterEqual('album_id', $photo['album_id'])->
                        getNextPhoto($photo, $ordering, $orderto);
                $prev_photo = $this->model->filterEqual('album_id', $photo['album_id'])->
                        getPrevPhoto($photo, $ordering, 'asc');
                break;
            default:
                $prev_photo = [];
                $next_photo = [];
                break;
        }

        return [$prev_photo, $next_photo];
    }

    private function getDownloadImages($photo) {

        $downloads = [];

        $presets = cmsCore::getModel('images')->getPresetsList();

        if (isset($photo['image']['original'])) {

            $photo['sizes']['original'] = [
                'width'  => $photo['width'],
                'height' => $photo['height']
            ];

            $presets['original'] = LANG_PARSER_IMAGE_SIZE_ORIGINAL;
        }

        $selected = $isset = false;

        foreach ($photo['image'] as $preset => $path) {

            $show = true;

            if (!empty($this->options['download_view'][$preset]) &&
                    !$this->cms_user->isInGroups($this->options['download_view'][$preset])) {
                $show = false;
            }
            if (!empty($this->options['download_hide'][$preset]) &&
                    $this->cms_user->isInGroups($this->options['download_hide'][$preset])) {
                $show = false;
            }

            if (!$isset && $show) {
                $selected = $isset = true;
            } else {
                $selected = false;
            }

            $downloads[$preset] = [
                'link'   => ($show ? href_to('photos', 'download', [$photo['id'], $preset]) . '?hash=' . $this->getDownloadHash() : ''),
                'size'   => $photo['sizes'][$preset]['width'] . '×' . $photo['sizes'][$preset]['height'],
                'name'   => $presets[$preset],
                'preset' => $preset,
                'image'  => ($show ? html_image_src($photo['image'], $preset, true) : ''),
                'select' => $selected
            ];
        }

        return $downloads;
    }

    private function getBigPreset($sizes) {

        if (isset($sizes[$this->options['preset']])) {
            return $this->options['preset'];
        }

        unset($sizes['original']);

        return $this->getMaxSizePresetName($sizes);
    }

    private function getMaxSizePresetName($sizes, $_size = 'width') {

        $__sizes = $presets = [];

        foreach ($sizes as $preset => $size) {
            $__sizes[] = $size[$_size];
            $presets[] = $preset;
        }

        return $presets[array_search(max($__sizes), $__sizes)];
    }

    private function buildPhotoDetails($photo, $album, $ctype) {

        $first_img = current($photo['image']);

        $details = [
            [
                'name'  => LANG_PHOTOS_FORMAT,
                'value' => strtoupper(pathinfo($first_img, PATHINFO_EXTENSION))
            ],
            [
                'name'  => LANG_PHOTOS_SIZE,
                'value' => $photo['width'] . '×' . $photo['height']
            ]
        ];

        if ($photo['date_photo']) {
            $details[] = [
                'name'  => LANG_PHOTOS_DATE,
                'value' => html_date_time($photo['date_photo'])
            ];
        }
        if (!empty($this->options['types'][$photo['type']])) {
            $details[] = [
                'name'  => LANG_PHOTOS_O_TYPE1,
                'value' => $this->options['types'][$photo['type']]
            ];
        }
        $details[] = [
            'name'  => LANG_PHOTOS_ALBUM,
            'value' => $album['title'],
            'link'  => href_to($ctype['name'], $album['slug']) . '.html'
        ];
        $details[] = [
            'name'  => LANG_HITS,
            'value' => html_spellcount($photo['hits_count'], LANG_HITS_SPELL)
        ];
        $details[] = [
            'name'  => LANG_PHOTOS_DOWNLOADS,
            'value' => $photo['downloads_count']
        ];

        list($details, $photo, $album, $ctype) = cmsEventsManager::hook('build_photo_details', [$details, $photo, $album, $ctype]);

        return $details;
    }

    private function getRelatedPhoto($photo) {

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

        $this->related_title = LANG_PHOTOS_RELATED;

        $this->model->filterNotEqual('id', $photo['id']);

        $this->model->filterRelated(['title', 'content'], $photo['title']);

        if (cmsUser::isAllowed('albums', 'view_all')) {
            $this->model->disablePrivacyFilter();
        }

        $this->model->limit($this->options['related_limit']);

        $photos = $this->getPhotosList();

        if (!$photos) {

            $this->model->limit($this->options['related_limit']);

            $this->model->filterEqual('album_id', $photo['album_id']);

            $this->model->filterNotEqual('id', $photo['id']);

            $photos = $this->getPhotosList();

            $this->related_title = LANG_PHOTOS_OTHER_IN_ALBUM;
        }

        return $photos;
    }
}
