<?php

namespace Ayaline\Bundle\EzAgendaCollectivitesBundle\Controller;

use eZ\Bundle\EzPublishCoreBundle\Controller;
use eZFunctionHandler;

/**
 * Class AgendaController
 * @package Ayaline\Bundle\EzAgendaCollectivitesBundle\Controller
 */
class AgendaController extends Controller
{

    /**
     * @param $locationId
     * @param $viewType
     * @param bool $layout
     * @param array $params
     * @return mixed
     */
    public function agendaAction($locationId, $viewType, $layout = false, array $params = array())
    {
        $repository = $this->getRepository();
        $locationService = $repository->getLocationService();
        $contentService = $repository->getContentService();
        $serviceTags = $this->container->get('ezpublish.api.service.tags');

        $location = $locationService->loadLocation($locationId);
        $content = $contentService->loadContent($location->contentInfo->id);

        $restreindreThematiques = array();
        foreach($content->getFieldValue('restreindre_thematiques')->tags as $tag){
            array_push($restreindreThematiques, $tag->keyword);
            foreach($serviceTags->loadTagChildren($tag) as $child){
                array_push($restreindreThematiques, $child->keyword);
            }
        }


        $dateStart = $this->getRequest()->query->has('date_start') ? $this->getRequest()->query->get('date_start') : "";
        $dateEnd = $this->getRequest()->query->has('date_end') ? $this->getRequest()->query->get('date_end') : "";
        $query = $this->getRequest()->query->has('query') ? $this->getRequest()->query->get('query') : "";
        $tags = $this->getRequest()->query->has('tags') ? $this->getRequest()->query->get('tags') : $restreindreThematiques;
        $types = $this->getRequest()->query->has('types') ? $this->getRequest()->query->get('types') : 0;
        $communes = $this->getRequest()->query->has('communes') ? $this->getRequest()->query->get('communes') : 0;
        $optionsDate = $this->getRequest()->query->has('optionsDate') ? $this->getRequest()->query->get('optionsDate') : 0;
        $optionsDateRetourEnImage = $this->getRequest()->query->has('optionsDateRetourEnImage') ? $this->getRequest()->query->get('optionsDateRetourEnImage') : 0;


        $destinationContentId=$content->getFieldValue('autre_agenda_source')->destinationContentId;
        $subtreeArray = $destinationContentId ? array($contentService->loadContent($destinationContentId)->contentInfo->mainLocationId) : array($locationId);

        $sortBy = array('evenement/mettre_en_avant' => 'desc',  'evenement/date_debut' => 'asc', 'evenement/titre' => 'asc');
//        $limit = $optionsDate == 0 ? 10 : $this->container->getParameter('events.number_content_per_page');
        $limit = $this->container->getParameter('events.number_content_per_page');

        $retourEnImage = isset($content->fields['mode_retour_en_image']) ? $content->getFieldValue('mode_retour_en_image')->bool : false;


        // par defaut les 10 prochains évenements
        if($retourEnImage && !$dateStart && !$dateEnd && $optionsDateRetourEnImage == 0){
            $date = strtotime("-30 day", strtotime(date('m/d/Y')));
            $dateStart = date('d/m/Y',$date );
            $dateEnd = date('d/m/Y');
        } elseif(!$dateStart && !$dateEnd && $optionsDate == 0){
            $dateStart = date('d/m/Y');
        }

        if($dateStart){
            $start = \DateTime::createFromFormat("d/m/Y H:i:s", $dateStart. ' 00:00:00');
        }
        if($dateEnd){
            $end   = \DateTime::createFromFormat("d/m/Y H:i:s", $dateEnd. ' 23:59:59');
        }

        $result = array();
        $permanentEvents = array();

        $searchResult = $this->search($query, $tags, $communes, $dateStart, $dateEnd, $subtreeArray, $sortBy, $limit, false, $retourEnImage , $types);

        $contentService = $this->getRepository()->getContentService();
        //Instanciation des objets eZ5
        $count = $searchResult['SearchCount'];
        $step  = new \DateInterval('P1D');
        foreach ($searchResult['SearchResult'] as $search) {
            $content = $contentService->loadContent($search->ContentObject->ID);

            if($content->getFieldValue('evenement_permanent')->bool ){
                $permanentEvents[$search->NodeID] = $content;
            }else{
                // dates events
                $dateStartEvent = isset($content->getFieldValue('date_debut')->date) ? $content->getFieldValue('date_debut')->date->format("m/d/Y") : "";
                $dateEndEvent = $content->getFieldValue('date_fin')->date ? $content->getFieldValue('date_fin')->date->format("m/d/Y") : $dateStartEvent;

                $dateStartEvent = \DateTime::createFromFormat("m/d/Y H:i:s", $dateStartEvent. ' 00:00:00');
                $dateEndEvent   = \DateTime::createFromFormat("m/d/Y H:i:s", $dateEndEvent. ' 23:59:59');

                // dates periode searsh
                if(!isset($start)){
                    $start = $dateStartEvent;
                }
                if(!isset($end)){
                    $end   = $dateEndEvent;
                }

                for($cur = clone $start; $cur <= $end; $cur->add($step)) {
                    if ($cur >= $dateStartEvent && $cur <= $dateEndEvent)
                    {
                        $result[$cur->format("Y/m/d")][$search->NodeID] = $content;

                    }
                }
            }
            if($dateEnd == ''){
                unset($end);
            }
        }
        ksort($result);

        $params += array(
            "permanentEvents" => $permanentEvents,
            "eventsList" => $result,
            "eventsCount" => $count,
            "restreindreThematiques" => $restreindreThematiques,
            "retourEnImage" => $retourEnImage
        );
        $response = $this->get('ez_content')->viewLocation($locationId, $viewType, $layout, $params);
        $response->setSharedMaxAge(86400);

        return $response;

    }


    /**
     * @param string $query
     * @param int $tags
     * @param int $communes
     * @param string $dateStart
     * @param string $dateEnd
     * @param array $subtreeArray
     * @param array $sortBy
     * @param null $limit
     * @param int $types
     * @return array
     */
    public function search( $query= '', $tags= 0, $communes= 0, $dateStart = '', $dateEnd = '', $subtreeArray = array(), $sortBy = array(), $limit = null, $remonteTimeLine = 0, $retourEnImage = 0, $types=0) {

        /** @var Logger $logger */
        $logger = $this->get('logger');
        $results = array();

        $classId = 'evenement';

        $searchResult = $this->getLegacyKernel()->runCallback(
            function () use ($query, $tags, $communes, $dateStart, $dateEnd, $classId, $subtreeArray, $sortBy, $limit, $remonteTimeLine, $retourEnImage, $types) {
                //Génération des paramètres de recherche
                $parameters = array();

                if ($query) {
                    $parameters['query'] = $query;
                }

                // Result count limit.
                if($limit){
                    $parameters['limit'] = (int)$limit;
                }

                $filter = array();

                if($remonteTimeLine){
                    array_push($filter, 'evenement/ne_jamais_remonter_sur_accueil_dans_timeline:0');
                }


                if($retourEnImage){
                    array_push($filter, 'evenement/retour_en_images:1');
                }

                if ($tags) {
                    $filterTags = array('or');
                    foreach ($tags as $tag) {
                        array_push($filterTags, 'evenement/thematiques:"' . trim($tag) . '"');
                    }

                    array_push($filter, $filterTags);
                }


                if ($types) {
                    $filterTags = array('or');
                    foreach ($types as $type) {
                        array_push($filterTags, 'evenement/types:"' . trim($type) . '"');
                    }

                    array_push($filter, $filterTags);
                }

                if ($communes) {
                    $filterTags = array('or');
                    foreach ($communes as $commune) {
                        array_push($filterTags, 'evenement/commune_tag:"' . trim($commune) . '"');
                    }

                    array_push($filter, $filterTags);
                }

                if ($dateStart) {
                    $dateTime = \DateTime::createFromFormat('d/m/Y H:i:s', $dateStart. ' 00:00:00');
                    $dateStart = strftime('%Y-%m-%dT%H:%M:%SZ', $dateTime->getTimestamp());
                }

                if ($dateEnd) {
                    $dateTime = \DateTime::createFromFormat('d/m/Y H:i:s', $dateEnd. ' 23:59:59');
                    $dateEnd = strftime('%Y-%m-%dT%H:%M:%SZ', $dateTime->getTimestamp());
                }

                if ($dateStart != '' && $dateEnd != '') {
                    $filterDate = array('or',
                        array('and', 'evenement/date_debut:[* TO ' . $dateEnd . '+1DAY]', 'evenement/date_fin:[' . $dateStart . '-1DAY TO *]'),
                        array('evenement/date_debut:[' . $dateStart . '-1DAY TO *]')
                    ) ;
                    array_push($filter, $filterDate);
                }elseif ($dateStart != '') {
                    $filterDate = array('or', 'evenement/date_debut:[' . $dateStart . '-1DAY TO *]', 'evenement/date_fin:[' . $dateStart . '-1DAY TO *]');
                    array_push($filter, $filterDate);
                }elseif ($dateEnd != '') {
                    $filterDate = array('or',
                        array('and','evenement/date_debut:[* TO ' . $dateEnd . '+1DAY]', 'evenement/date_fin:[* TO ' . $dateEnd . '+1DAY]'),
                        array('and','evenement/date_debut:[* TO ' . $dateEnd . '+1DAY]', 'evenement/date_fin:[' . $dateEnd . '-1DAY TO *]'),

                    );
                    array_push($filter, $filterDate);
                }

                $parameters['filter'] = $filter;

                //Sort definition
                if($sortBy){
                    $parameters['sort_by'] = $sortBy;
                }

                if (count($subtreeArray)) {
                    $parameters['subtree_array'] = $subtreeArray;
                }
                //Class ID limitation
                $parameters['class_id'] = $classId;

                // eZFunctionHandler::execute is the equivalent for a legacy template fetch function
                // The following is the same than fetch( 'ezfind', 'search', hash(...) )
                return eZFunctionHandler::execute(
                    'ezfind',
                    'search',
                    $parameters
                );
            }
        );

        if ($searchResult !== null && isset($searchResult['SearchExtras']) && !$searchResult['SearchExtras']->attribute('hasError')) {
            $results = $searchResult;
        } elseif ($searchResult !== null && isset($searchResult['SearchExtras'])) {
            $logger->error($searchResult['SearchExtras']->attribute('error'));
        } else {
            $logger->error("eZFind non activé!");
        }

        return $results;
    }

    /**
     * @param $parentTags
     * @param $paramTags
     * @param array $restreindre_thematiques
     * @param bool|false $getSousTag
     * @param string $template
     * @return mixed
     */
    public function tagListAction($parentTags, $paramTags, $restreindre_thematiques = array(), $getSousTag = false, $template = "AyalineEzAgendaCollectivitesBundle::parts/tag_list.html.twig")
    {
        $tagsList = array();
        $tagsListChildren = array();

        $serviceTags = $this->container->get('ezpublish.api.service.tags');

        // si il y a une restriction sur les thématiques
        if($restreindre_thematiques){
            $tagsList = $restreindre_thematiques;
        }else{
            if($parentTags){
                $tagsList = $serviceTags->loadTagChildren($parentTags);
            }
        }

        // sort by keyword
        uasort($tagsList,array("self", "sortTag"));

        if($getSousTag){
            foreach($tagsList as $tag){
                $tagsListChildren[$tag->id] = $serviceTags->loadTagChildren($tag);

                // sort by keyword
                uasort($tagsListChildren[$tag->id],array("self", "sortTag"));
            }
        }

        return $this->render(
            $template,
            array(
                "tagList" => $tagsList,
                "tagsListChildren" => $tagsListChildren,
                "paramTag" => $paramTags
            )
        );
    }

    /**
     * @param $tag1
     * @param $tag2
     * @return int
     */
    public static function sortTag($tag1,$tag2)
    {
        return strcmp($tag1->keyword, $tag2->keyword);
    }



    /**
     * @param bool $locationId
     * @param bool $limit
     * @param string $template
     * @return mixed
     */
    public function embedHomeAction($locationId = false, $limit = false, $template="AyalineEzAgendaCollectivitesBundle::home/agenda_1.html.twig", $remonteTimeLine = false)
    {
        $contentService = $this->getRepository()->getContentService();
        $locationService = $this->getRepository()->getLocationService();
        $helperContent = $this->get('ayaline_tools.tools.content');

        $rootLocation = $this->getRootLocation();
        $configGeneralIdentifier = $this->container->hasParameter('identifier.config_general.'.$this->getRequest()->get('siteaccess')->name) ? $this->container->getParameter('identifier.config_general.'.$this->getRequest()->get('siteaccess')->name) : 'configuration_generale';

        $configurationGenerale = $helperContent->contentList(
            $rootLocation->id,
            array($configGeneralIdentifier),
            array(),
            1
        );

        if (count($configurationGenerale) > 0) {
            $rootAgendaId = isset($configurationGenerale[0]->fields['agenda_racine']) ? $configurationGenerale[0]->getField('agenda_racine')->value->destinationContentId : null;
            if(isset($rootAgendaId) && $rootAgendaId){
                $AgendaRootContent = $contentService->loadContent($rootAgendaId);
                $rootAgendaLocationId = $AgendaRootContent->contentInfo->mainLocationId;
            }
            $rootAgendaTitle = isset($configurationGenerale[0]->fields['agenda_intitule_accueil']) ? $configurationGenerale[0]->getField('agenda_intitule_accueil')->value->text : null;
        }


        if (!$limit) {
            $limit = (int) $this->container->getParameter('events.embed.number_content_per_block');
        }

        // root content
        $rootLocation = $locationService->loadLocation($locationId);
        $rootContent = $contentService->loadContent($rootLocation->contentInfo->id);

        $eventsList = array();

        if (isset($rootContent->fields['agenda_selection_manuelle'])) {
            $contentIds = $rootContent->getField('agenda_selection_manuelle')->value->destinationContentIds;
        }

        if (!empty($contentIds)) {
            foreach ($contentIds as $contentId) {
                $eventContent = $contentService->loadContent($contentId);
                $eventLocation = $locationService->loadLocation($eventContent->contentInfo->mainLocationId);
                if (!$eventLocation->hidden) {
                    // array_push($eventsList, $eventContent);
                    $eventsList[$eventLocation->id] = $eventContent;
                }
            }
        } else {
            if(isset($rootAgendaLocationId) && $rootAgendaLocationId){
                $dateStart = date('d/m/Y');
                $sortBy = array('evenement/date_debut' => "asc");
                $searchResult = $this->search('', 0, 0, $dateStart, '', array($rootAgendaLocationId), $sortBy, $limit, $remonteTimeLine );

                foreach ($searchResult['SearchResult'] as $search) {
                    //array_push($eventsList, $contentService->loadContent($search->ContentObject->ID));
                    $eventsList[$search->NodeID] = $contentService->loadContent($search->ContentObject->ID);
                }
            }
        }

        return $this->render(
            $template,
            array(
                "rootTitle" => isset($rootAgendaTitle) ? $rootAgendaTitle : '',
                "rootID" => isset($rootAgendaLocationId) ? $rootAgendaLocationId : null,
                "eventsList" => $eventsList
            )
        );
    }

    /**
     * @param bool $locationId
     * @param array $tags
     * @param string $template
     * @param null $currentDetailLocationId
     * @param bool $limit
     * @return mixed
     */
    public function embedAction($locationId = false, $tags= array(), $template="AyalineEzAgendaCollectivitesBundle::embed/events.html.twig", $currentDetailLocationId = null, $limit =false)
    {
        $eventsList = array();
        $contentService = $this->getRepository()->getContentService();

        if(!$limit){
            $limit = (int) $this->container->getParameter('events.embed.number_content_per_block');
        }

        $dateStart = date('d/m/Y');
        $sortBy = array('evenement/date_debut' => "asc");
        $searchResult = $this->search('', $tags, 0, $dateStart, '', array($locationId), $sortBy, $limit );

        foreach ($searchResult['SearchResult'] as $search) {
            if($currentDetailLocationId != $search->NodeID){
                //array_push($eventsList, $contentService->loadContent($search->ContentObject->ID));
                $eventsList[$search->NodeID] = $contentService->loadContent($search->ContentObject->ID);
            }
        }

        return $this->render(
            $template,
            array(
                "eventsList" => $eventsList,
                "currentDetailLocationId" => $currentDetailLocationId,
                "locationId" => $locationId,
                "tags" => $tags
            )
        );
    }

    /**
     * @param $locationId
     * @param $template
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function getTimeLineAction($locationId, $template, $charLimit)
    {
        $repository = $this->getRepository();
        $locationService = $repository->getLocationService();
        $contentService = $repository->getContentService();
        $serviceTags = $this->container->get('ezpublish.api.service.tags');

        $location = $locationService->loadLocation($locationId);
        $content = $contentService->loadContent($location->contentInfo->id);

        $restreindreThematiques = array();
        foreach($content->getFieldValue('restreindre_thematiques')->tags as $tag){
            array_push($restreindreThematiques, $tag->keyword);
            foreach($serviceTags->loadTagChildren($tag) as $child){
                array_push($restreindreThematiques, $child->keyword);
            }
        }

        $rootLocation = $this->getRootLocation();
        $rootContent = $contentService->loadContent($rootLocation->contentInfo->id);
        $helperContent = $this->get('ayaline_tools.tools.content');
        $configurationGenerale = $helperContent->contentList(
            $rootLocation->id,
            array('configuration_generale'),
            array(),
            1
        );

        $rootAgendaId = isset($configurationGenerale[0]->fields['agenda_racine']) ? $configurationGenerale[0]->getField('agenda_racine')->value->destinationContentId : null;
        $rootAgenda = $rootAgendaId ? $contentService->loadContent($rootAgendaId) : null;
        $rootRetourEnImageId = isset($configurationGenerale[0]->fields['retour_en_image_racine']) ? $configurationGenerale[0]->getField('retour_en_image_racine')->value->destinationContentId : null;
        $rootRetourEnImage = $rootRetourEnImageId ? $contentService->loadContent($rootRetourEnImageId) : null;

        $dateStart = $this->getRequest()->request->has('date_start') ? $this->getRequest()->request->get('date_start') : "";


        $destinationContentId=$content->getFieldValue('autre_agenda_source')->destinationContentId;
        $subtreeArray = $destinationContentId ? array($contentService->loadContent($destinationContentId)->contentInfo->mainLocationId) : array($locationId);

        $sortBy = array('evenement/mettre_en_avant' => 'desc',  'evenement/date_debut' => 'asc');
        $limit = isset($rootContent->fields['agenda_nombre_max_timeline_accueil']) ? $rootContent->getField('agenda_nombre_max_timeline_accueil')->value->value :20;


        // par defaut les 10 prochains évenements
        if(!$dateStart){
            $dateStart = date('d/m/Y');
        }

        $result = array();

        $searchResult = $this->search('', $restreindreThematiques, 0, $dateStart, '', $subtreeArray, $sortBy, $limit, true );

        $contentService = $this->getRepository()->getContentService();

        $filterBar = $this->container->getParameter('agenda_display_filter_bar');

        // count
        $count = $searchResult['SearchCount'];

        if($dateStart){
            $start = \DateTime::createFromFormat("d/m/Y H:i:s", $dateStart. ' 00:00:00');
        }

        //Instanciation des objets eZ5
        foreach ($searchResult['SearchResult'] as $search) {
            $content = $contentService->loadContent($search->ContentObject->ID);

            // dates events
            $dateStartEvent = isset($content->getFieldValue('date_debut')->date) ? $content->getFieldValue('date_debut')->date->format("m/d/Y") : "";
            $dateEndEvent = $content->getFieldValue('date_fin')->date ? $content->getFieldValue('date_fin')->date->format("m/d/Y") : $dateStartEvent;

            $dateStartEvent = \DateTime::createFromFormat("m/d/Y H:i:s", $dateStartEvent. ' 00:00:00');
            $dateEndEvent   = \DateTime::createFromFormat("m/d/Y H:i:s", $dateEndEvent. ' 23:59:59');

            // dates periode searsh
            if(!isset($start)){
                $start = $dateStartEvent;
            }
            if(!isset($end)){
                $end   = \DateTime::createFromFormat("d/m/Y", date('d/m/Y', strtotime("+1 year")));
            }
            $step  = new \DateInterval('P1D');

            for($cur = clone $start; $cur <= $end; $cur->add($step)) {
                if ($cur >= $dateStartEvent && $cur <= $dateEndEvent)
                {
                    $result[$cur->format("m/d/Y")][$search->NodeID] = $content;

                }
            }

        }

        foreach($result as $day => $contents){
            // trie par durée
            uasort($contents, function ($content1, $content2)
            {
                // dates events
                $dateStartEvent = isset($content1->getFieldValue('date_debut')->date) ? $content1->getFieldValue('date_debut')->date->format("m/d/Y") : "";
                $dateEndEvent = $content1->getFieldValue('date_fin')->date ? $content1->getFieldValue('date_fin')->date->format("m/d/Y") : $dateStartEvent;

                $dateStartEvent = new \DateTime($dateStartEvent);
                $dateEndEvent = new \DateTime($dateEndEvent);
                $interval = $dateEndEvent->diff($dateStartEvent);

                $dateStartEvent2 = isset($content2->getFieldValue('date_debut')->date) ? $content2->getFieldValue('date_debut')->date->format("m/d/Y") : "";
                $dateEndEvent2 = $content2->getFieldValue('date_fin')->date ? $content2->getFieldValue('date_fin')->date->format("m/d/Y") : $dateStartEvent2;

                $dateStartEvent2 = new \DateTime($dateStartEvent2);
                $dateEndEvent2 = new \DateTime($dateEndEvent2);
                $interval2 = $dateEndEvent2->diff($dateStartEvent2);

                if ($interval->days == $interval2->days) {
                    return 0;
                }

                if($content1->getFieldValue('mettre_en_avant')->bool){
                    return -1;
                }elseif($content2->getFieldValue('mettre_en_avant')->bool){
                    return 1;
                }elseif($interval->days < $interval2->days && !$content1->getFieldValue('mettre_en_avant')->bool && !$content2->getFieldValue('mettre_en_avant')->bool){
                    return -1;
                }elseif($interval->days > $interval2->days && !$content1->getFieldValue('mettre_en_avant')->bool && !$content2->getFieldValue('mettre_en_avant')->bool){
                    return 1;
                }

            }
            );
            $result[$day] = $contents;
        }

        // trie par jour
        ksort($result);

        return $this->render(
            $template,
            array(
                "rootContent" => $rootContent,
                "rootAgendaId" => $rootAgenda ? $rootAgenda->contentInfo->mainLocationId : null,
                "rootRetourEnImageId" => $rootRetourEnImage ? $rootRetourEnImage->contentInfo->mainLocationId : null,
                "eventsList" => $result,
                "eventsCount" => $count,
                "restreindreThematiques" => $restreindreThematiques,
                "dateStart" => $dateStart,
                "charLimit" => $charLimit,
                "filterBar" => $filterBar
            )
        );

    }

}
