<?php

namespace AppBundle\Controller;

use AppBundle\Entity\BreadcrumbEntry;
use AppBundle\Entity\Page;
use AppBundle\Entity\TravelProgram;
use AppBundle\Form\SearchRequestType;
use AppBundle\Util;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Query\Expr;
use Gedmo\Tree\TreeListener;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Stopwatch\Stopwatch;

class DefaultController extends Controller
{
    /**
     * @return EntityManager
     */
    public function getEntityManager()
    {
        return $this->getDoctrine()->getManager();
    }

    public function defaultAction(Request $request)
    {
        // #TODO 404
        die ("caught");
    }

    /**
     * @Route("/")
     */
    public function homeAction()
    {
        //$departures = $this->getEntityManager()->getRepository('AppBundle:TravelDeparturePoint')->findAll();
        $destinations = $this->getEntityManager()->getRepository('AppBundle:TravelCountry')->findAll();

        return $this->render('default/pages/home.html.twig', [
            'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
            'destinations' => $destinations,
            'startDate' => new \DateTime('+5 day'),
            'endDate' => new \DateTime('+19 day')
        ]);
    }

    public function cmsDefaultAction(Page $page)
    {
        return $this->render('default/pages/default.html.twig', [
          'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
          'page' => $page
        ]);
    }

    public function cmsOverviewAction(Page $page)
    {
        return $this->render('default/pages/overview.html.twig', [
            'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
            'page' => $page,

            // #WORKAROUND Special navigation logic here adapted from the old website: Don't show child entries
            // #TODO Only applies at level 0
            /*
            'nav_pages' => $page->getChildren(),
            'nav_child_pages' => [],
            'nav_open_node' => null
            */
        ]);
    }

    public function cmsTravelProgramOverviewAction(Page $page)
    {
        $childPages =
          $this->getEntityManager()->getRepository('AppBundle:Page')->getChildrenWithTravelProgramsAndDates($page);

        $nonMediated = [];
        $mediated = [];
        foreach ($childPages as $childPage)
        {
            if ($childPage->getStatus() == 1 && $childPage->getTravelProgram() &&
                $childPage->getTravelProgram()->getIsMediated())
            {
                $mediated[] = $childPage;
            }
            else
            {
                $nonMediated[] = $childPage;
            }
        }
        // We only need a separation if there are mediated AND non mediated travel programs
        if (empty($nonMediated) && !empty($mediated))
        {
            $childPages = $mediated;
        }
        else
        {
            $childPages = $nonMediated;
        }

        return $this->render('default/pages/travelProgramOverview.html.twig', [
            'base_dir'    => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
            'page'        => $page,
            'child_pages' => $childPages,
            'mediated_child_pages' => $mediated,
        ]);
    }

    public function cmsTravelProgramAction(Page $page)
    {
        $this->getDoctrine()->getRepository('AppBundle:TravelPeriod')->getTrueTravelPeriods($page->getTravelProgram());

        // replace this example code with whatever you need
        return $this->render('default/pages/travelProgram.html.twig', [
            'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
            'page' => $page,
            'travel_program' => $page->getTravelProgram()
        ]);
    }

    /**
     * @Route("/suche")
     */
    public function searchAction(Request $request)
    {
        $em = $this->getEntityManager();

        $form = $this->createForm(SearchRequestType::class);
        $form->handleRequest($request);

        if ($form->isValid())
        {
            $data = $form->getData();

            $destinationIds = [];
            if (!empty($data['c']))
            {
                $destinationIds = [$data['c']->getId()];
            }
            if (!empty($destinationIds) && !empty($data['c2']))
            {
                $destinationIds[] = $data['c2']->getId();
            }

            $r = $this->getDoctrine()->getRepository('AppBundle:TravelPeriod')->getTravelProgramsWithTravelDatesForTimePeriod(
                $data['b'], $data['e'], $destinationIds, count($destinationIds) > 1);
        }
        else
        {
            $r = [];
        }

        return $this->render('default/pages/search.html.twig', [
            'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
            'breadcrumb_entries' => [new BreadcrumbEntry('Suchen')],
            'search_form' => $form->createView(),
            'travel_programs' => $r,
        ]);
    }

    public function headerAction()
    {
        $qb = $this->getEntityManager()->createQueryBuilder();
        $navPages = $qb
          ->from('AppBundle:Page', 'page')
          ->select('page')
          ->leftJoin('page.children', 'childPage', Expr\Join::WITH, 'childPage.status > 0')
          ->addSelect('childPage')
          ->where('page.status > 0')
          ->andWhere('page.template = \'overview\'')
          ->andWhere('page.lvl = 0')
          ->orderBy('page.lft,page.title,childPage.lft,childPage.title')
          ->getQuery()
          ->execute()
        ;
        return $this->render('default/components/header.html.twig', [
            'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
            'nav_pages' => $navPages,
        ]);
    }

    public function breadcrumbAction(Page $page)
    {
        return $this->render('default/components/breadcrumb.html.twig', [
          'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
          'breadcrumb_entries' => Util::createBreadcrumb($page),
        ]);
    }

    public function navSidebarWidgetAction(Page $page)
    {
        $pageRepo = $this->getEntityManager()->getRepository('AppBundle:Page');
        $view = [
            'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
            'page' => $page,
        ];

        if ($page->getHasChildren())
        {
            if ($page->getLvl() == 0)
            {
                $view['nav_pages'] = $page->getChildren();
                $view['nav_child_pages'] = [];
            }
            else
            {
                $view['nav_pages'] = $pageRepo->getSiblings($page);
                $view['nav_child_pages'] = $page->getChildren();
            }
            $view['nav_open_node'] = $page;
        }
        else
        {
            $parent = $page->getParent();
            if ($parent)
            {
                $view['nav_pages'] = $pageRepo->getSiblings($parent);
                if (empty($view['nav_pages']))
                {
                    $view['nav_pages'] = $pageRepo->getSiblings($page);
                }
                else
                {
                    $view['nav_child_pages'] = $pageRepo->getSiblings($page);
                }
                $view['nav_open_node'] = $parent;
            }
            else
            {
                $view['nav_pages'] = $pageRepo->getSiblings($page);
                $view['nav_child_pages'] = [];
                $view['nav_open_node'] = null;
            }
        }
        return $this->render('default/components/sidebar/navSidebarWidget.html.twig', $view);
    }

    public function searchSidebarWidgetAction(Page $page)
    {
        $combinedDestination = null;
        if ($page->getTravelProgram())
        {
            $countries = $page->getTravelProgram()->getCountries();
            $destination = $countries->first();
            if (count($countries) > 1)
            {
                $combinedDestination = $countries[1];
            }
        }
        else
        {
            $destination = $page->getCountry();
        }
        return $this->render('default/components/sidebar/searchSidebarWidget.html.twig', [
            'search_form' => $this->createForm(SearchRequestType::class, [
                'b' => new \DateTime('+5 day'),
                'e' => new \DateTime('+19 day'),
                'c' => $destination,
                'c2' => $combinedDestination,
            ])->createView()
        ]);
    }

    /*
    Suche Kindknoten
    Für jeden Kindknoten
        ++LFT
        Setze LFT
        f()
        ++LFT
        RGT = LFT
        Setze RGT
    */

    /**
     * @Route("/create-tree")
     */
    public function createTreeAction()
    {
        set_time_limit(0);
        ini_set('memory_limit', '2048M');

        $em = $this->getEntityManager();

        $em->getConnection()->executeUpdate(
            'UPDATE page SET lvl = NULL, lft = NULL, rgt = NULL, parent_id = NULL, tree_root = NULL');

        foreach ($em->getEventManager()->getListeners() as $event => $listeners) {
            foreach ($listeners as $hash => $listener) {
                if ($listener instanceof TreeListener)
                {
                    $em->getEventManager()->removeEventListener($event, $listener);
                }
            }
        }

        $em->beginTransaction();

        // Add missing owner relation for catalog root pages (e.g. children of 'aegypten-reisen')
        $em->getConnection()->executeUpdate('UPDATE page SET owner = 47 WHERE catalog_id = 3 AND owner = 0');
        $em->getConnection()->executeUpdate('UPDATE page SET owner = 66 WHERE catalog_id = 6 AND owner = 0');
        $em->getConnection()->executeUpdate('UPDATE page SET owner = 2803 WHERE catalog_id = 14 AND owner = 0');

        $lft = 0;
        $this->createTree(0, $lft, 0);
        $em->flush();

        // Reset the owner field to avoid problems in the old website
        $em->getConnection()->executeUpdate('UPDATE page SET owner = 0 WHERE parent_id = 47 AND catalog_id = 3');
        $em->getConnection()->executeUpdate('UPDATE page SET owner = 0 WHERE parent_id = 66 AND catalog_id = 6');
        $em->getConnection()->executeUpdate('UPDATE page SET owner = 0 WHERE parent_id = 2803 AND catalog_id = 14');

        $em->commit();

        die("DONE.");
    }

    private function createTree($owner, &$lft, $lvl, $root = null)
    {
        $em = $this->getEntityManager();

        $qb = $em->createQueryBuilder()->from('AppBundle:Page', 'p')->select('p');
        $qb->where($qb->expr()->eq('p.owner', $owner));
        if ($owner == 0)
        {
            $qb->orWhere('p.owner IS NULL');
        }
        $qb->orderBy('p.order');
        $qb->addOrderBy('p.title');
        $pages = $qb->getQuery()->execute();
        foreach ($pages as $page)
        {
            /** @var Page $page */

            if ($owner == 0)
            {
                $root = $page->getId();
            }

            ++$lft;
            $page->setLft($lft);
            $page->setLvl($lvl);
            $page->setRoot($em->getReference('AppBundle:Page', $root));
            if ($owner != 0)
            {
                $page->setParent($em->getReference('AppBundle:Page', $owner));
            }

            $this->createTree($page->getId(), $lft, $lvl + 1, $root);

            ++$lft;
            $page->setRgt($lft);

            $em->persist($page);
        }
    }
}
