<?php

declare(strict_types=1);

namespace vonRotenberg\RealEstateListingBundle\Controller\FrontendModule;

use vonRotenberg\RealEstateListingBundle\Model\ManagedPropertyModel;
use Contao\ArrayUtil;
use Contao\CoreBundle\Controller\FrontendModule\AbstractFrontendModuleController;
use Contao\CoreBundle\DependencyInjection\Attribute\AsFrontendModule;
use Contao\CoreBundle\Exception\ResponseException;
use Contao\CoreBundle\Image\Studio\Figure;
use Contao\CoreBundle\Image\Studio\FigureBuilder;
use Contao\CoreBundle\Twig\FragmentTemplate;
use Contao\File;
use Contao\FilesModel;
use Contao\Input;
use Contao\ModuleModel;
use Contao\PageModel;
use Contao\StringUtil;
use Contao\System;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

#[AsFrontendModule(category: 'vr_real_estate')]
class ManagedPropertyController extends AbstractFrontendModuleController
{
    public const TYPE = 'managed_property';
    protected function getResponse(FragmentTemplate $template, ModuleModel $model, Request $request): Response
    {

        $arrAssets = [];
        $arrFilterOptions = [
            'city' => []
        ];
        $arrFilterSelected = [];
        $arrAssetsOptions = [];

        $jumpTo = PageModel::findByPk($model->jumpTo);
        $urlGenerator = System::getContainer()->get('contao.routing.content_url_generator');

        // Filter
        if (isset($_GET['filter']) && \is_array(Input::get('filter')))
        {
            foreach (Input::get('filter') as $filter=>$value)
            {
                if (in_array($filter, array_keys($arrFilterOptions)) && !empty($value))
                {
                    $rawValue = StringUtil::decodeEntities($value);
                    $arrFilterSelected[$filter] = $rawValue;

                    if (preg_match('/^.*<>.*$/',$rawValue))
                    {
                        list($start,$stop) = preg_split('/<>/',$rawValue, 2);
                        $arrAssetsOptions['column'][$filter] = "$filter BETWEEN $start AND $stop";
                    } else {
                        $arrAssetsOptions['column'][$filter] = "$filter = ?";
                        $arrAssetsOptions['value'][$filter] = $rawValue;
                    }
                }
            }
        }

        if (($assets = ManagedPropertyModel::findAllPublished(0,0,$arrAssetsOptions)) === null)
        {
            return $template->getResponse();
        }

        // Figure Builder
        $figureBuilder = System::getContainer()
            ->get('contao.image.studio')
            ->createFigureBuilder()
            ->setSize($model->imgSize)
            ->setLightboxGroupIdentifier('lb' . $model->id);

        foreach ($assets as $asset)
        {
            $arrItem = array_merge($asset->row(), [
                'teaserFigure' => $this->getImageFigures($asset->gallerySRC, $figureBuilder, $asset->orderSRC, 1),
                'detailsUrl'   => $jumpTo !== null ? $urlGenerator->generate($jumpTo, ['parameters'=>'/items/'.$asset->id]) : null
            ]);

            $arrAssets[] = $arrItem;
        }

        // Populate filters
        $filterAssets = ManagedPropertyModel::findAllPublished();
        foreach ($filterAssets as $asset)
        {
            // Filter options
            if (!empty($asset->city))
            {
                $tmpOptions = $arrAssetsOptions;
                $tmpOptions['column'] = array_merge((isset($arrAssetsOptions['column']) ? $arrAssetsOptions['column'] : []),['city'=>'city = ?']);
                $tmpOptions['value'] = array_merge((isset($arrAssetsOptions['value']) ? $arrAssetsOptions['value'] : []),['city'=>$asset->city]);
                $count = ManagedPropertyModel::countAllPublished($tmpOptions);
                $arrFilterOptions['city'][$asset->city] = $asset->city . ' ('.$count.')';
            }
        }

        foreach (array_keys($arrFilterOptions) as $filterName)
        {
            $arrFilterOptions[$filterName] = array_unique($arrFilterOptions[$filterName]);
        }

        // Set template data
        $template->set('filterOptions',$arrFilterOptions);
        $template->set('filter',$arrFilterSelected);
        $template->set('assets',$arrAssets);

        // Handle ajax
        if ($request->headers->get('VR-Ajax') == 'RePropertiesList')
        {
            throw new ResponseException($template->getResponse());
        }

        return $template->getResponse();
    }

    /**
     * @param string|array  $strUuids
     * @param FigureBuilder $figureBuilder
     * @param string|array  $strOrder
     *
     * @return array|Figure
     * @throws \Exception
     */
    public function getImageFigures($strUuids, $figureBuilder, $strOrder = null, int $intLimit = 0, int $intOffset = 0)
    {
        $arrImageFigures = [];

        if (($imageFiles = FilesModel::findMultipleByUuids(StringUtil::deserialize($strUuids))) !== null)
        {
            $images = array();
            while ($imageFiles->next())
            {
                // Continue if the files has been processed or does not exist
                if (isset($images[$imageFiles->path]) || !file_exists(System::getContainer()->getParameter('kernel.project_dir') . '/' . $imageFiles->path))
                {
                    continue;
                }

                // Single files
                if ($imageFiles->type == 'file')
                {
                    $objFile = new File($imageFiles->path);

                    if (!$objFile->isImage)
                    {
                        continue;
                    }

                    // Add the image
                    $images[$imageFiles->path] = $imageFiles->current();
                } // Folders
                else
                {
                    $objSubfiles = FilesModel::findByPid($imageFiles->uuid, array('order' => 'name'));

                    if ($objSubfiles === null)
                    {
                        continue;
                    }

                    while ($objSubfiles->next())
                    {
                        // Skip subfolders
                        if ($objSubfiles->type == 'folder')
                        {
                            continue;
                        }

                        $objFile = new File($objSubfiles->path);

                        if (!$objFile->isImage)
                        {
                            continue;
                        }

                        // Add the image
                        $images[$objSubfiles->path] = $objSubfiles->current();
                    }
                }
            }

            if ($strOrder !== null)
            {
                $images = ArrayUtil::sortByOrderField($images, $strOrder);
            }
            $images = array_values($images);

            // Offset images
            if ($intOffset > 0)
            {
                $images = \array_slice($images, ($intOffset < count($images) ? $intOffset : count($images)));
            }

            // Limit number of images
            if ($intLimit > 0)
            {
                $images = \array_slice($images, 0, $intLimit);
            }

            // Build figures of images
            foreach ($images as $image)
            {
                $figure = $figureBuilder
                    ->fromFilesModel($image)
                    ->build();

                $arrImageFigures[] = $figure;
            }

        }
        return count ($arrImageFigures) === 1 && $intLimit === 1 ? array_shift($arrImageFigures) : $arrImageFigures;
    }
}