<?php

namespace Plugin\ApgSimpleCalendar\Twig\Extension;

use Carbon\Carbon;
use Doctrine\ORM\EntityManagerInterface;
use Plugin\ApgSimpleCalendar\Entity\Config;
use Plugin\ApgSimpleCalendar\Entity\Holiday;
use Plugin\ApgSimpleCalendar\Repository\ConfigRepository;
use Plugin\ApgSimpleCalendar\Repository\HolidaysRepository;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class PluginExtension extends AbstractExtension
{

    /** @var ConfigRepository */
    protected $configRepository;

    protected $scConfigRepository;
    /** @var HolidaysRepository */
    protected $holidaysRepository;

    /**
     * @var EntityManagerInterface
     */
    protected $em;

    public function __construct(
        ConfigRepository $configRepository,
        HolidaysRepository $holidaysRepository,
        EntityManagerInterface $em
    )
    {
        $this->configRepository = $configRepository;
        $this->holidaysRepository = $holidaysRepository;
        $this->em = $em;
    }

    public function getFunctions()
    {
        return [
            new TwigFunction('apg_sc_get_month_days', [$this, 'getMonthDays']),
            new TwigFunction('apg_sc_get_this_month_days', [$this, 'getThisMonthDays']),
            new TwigFunction('apg_sc_get_next_month_days', [$this, 'getNextMonthDays']),
        ];
    }

    /**
     * @return mixed
     */
    public function getMonthDays($addMonth)
    {

        $nextMonthTimeStamp = mktime(0, 0, 0, date('n') + $addMonth, 1, date('Y'));

        $year = date('Y', $nextMonthTimeStamp);
        $month = date('m', $nextMonthTimeStamp);

        $endOfMonth = date('t', strtotime($year . $month . '01'));
        $firstOfWeek = date('w', strtotime($year . $month . '01'));

        return $this->shapingCalendarData($year, $month, $endOfMonth, $firstOfWeek);
    }

    /**
     * @return mixed
     */
    public function getThisMonthDays()
    {
        return $this->getMonthDays(0);
    }

    /**
     * @return mixed
     */
    public function getNextMonthDays()
    {
        return $this->getMonthDays(1);
    }

    protected function shapingCalendarData($year, $month, $endOfMonth, $firstOfWeek)
    {


        $result['year'] = $year;
        $result['month'] = $month;

        $monthDays = [];
        $j = 0;
        for ($i = 0; $i < $firstOfWeek; $i++) {
            $monthDays[$j][] = [
                'day' => '',
                'holiday' => false,
                'name' => '',
            ];
        }

        /** @var Config $Config */
        $Config = $this->configRepository->getWithCache();

        $weekHolidays = $Config->getRegularHolidaysArr();

        /** @var Holiday[] $Holidays */
        $Holidays = $this->holidaysRepository->findAllWithCache();

        $holidayMap = [];
        foreach ($Holidays as $Holiday) {
            $holidayMap[$Holiday->getTargetDate()->format('Y-m-d')] = $Holiday;
        }
        for ($i = 1; $i <= $endOfMonth; $i++) {
            $date = Carbon::createFromDate($year, $month, $i);
            // 日曜で次の行
            if (isset($monthDays[$j]) && count($monthDays[$j]) === 7) {
                $j++;
            }
            if (isset($holidayMap[$date->format('Y-m-d')])) {
                $tmp = $holidayMap[$date->format('Y-m-d')];
                $monthDays[$j][] = [
                    'day' => $i,
                    'holiday' => true,
                    'name' => $tmp->getName(),
                ];
                continue;
            }

            $weekNumber = $date->dayOfWeek;
            switch ($weekNumber) {
                case 0: // 日曜日
                    $weekNumber = 7;
                    break;
            }
            if (in_array($weekNumber, $weekHolidays)) {
                $monthDays[$j][] = [
                    'day' => $i,
                    'holiday' => true,
                    'name' => '定休日',
                ];
            } else {
                $monthDays[$j][] = [
                    'day' => $i,
                    'holiday' => false,
                    'name' => '',
                ];

            }

        }
        for ($i = count($monthDays[$j]); $i < 7; $i++) {
            $monthDays[$j][] = [
                'day' => '',
                'holiday' => false,
                'name' => '',
            ];
        }

        $result['days'] = $monthDays;
        return $result;


    }
}