<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

/**
 * Trait Week.
 *
 * week and ISO week number, year and count in year.
 *
 * Depends on the following properties:
 *
 * @property int $daysInYear
 * @property int $dayOfWeek
 * @property int $dayOfYear
 * @property int $year
 *
 * Depends on the following methods:
 *
 * @method static addWeeks(int $weeks = 1)
 * @method static copy()
 * @method static dayOfYear(int $dayOfYear)
 * @method string getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
 * @method static next(int|string $day = null)
 * @method static startOfWeek(int $day = 1)
 * @method static subWeeks(int $weeks = 1)
 * @method static year(int $year = null)
 */
trait Week
{
    /**
     * Set/get the week number of year using given first day of week and first
     * day of year included in the first week. Or use ISO format if no settings
     * given.
     *
     * @param int|null $year      if null, act as a getter, if not null, set the year and return current instance.
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int|static
     */
    public function isoWeekYear($year = null, $dayOfWeek = null, $dayOfYear = null)
    {
        return $this->weekYear(
            $year,
            $dayOfWeek ?? 1,
            $dayOfYear ?? 4
        );
    }

    /**
     * Set/get the week number of year using given first day of week and first
     * day of year included in the first week. Or use US format if no settings
     * given (Sunday / Jan 6).
     *
     * @param int|null $year      if null, act as a getter, if not null, set the year and return current instance.
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int|static
     */
    public function weekYear($year = null, $dayOfWeek = null, $dayOfYear = null)
    {
        $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
        $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;

        if ($year !== null) {
            $year = (int) round($year);

            if ($this->weekYear(null, $dayOfWeek, $dayOfYear) === $year) {
                return $this->avoidMutation();
            }

            $week = $this->week(null, $dayOfWeek, $dayOfYear);
            $day = $this->dayOfWeek;
            $date = $this->year($year);
            switch ($date->weekYear(null, $dayOfWeek, $dayOfYear) - $year) {
                case 1:
                    $date = $date->subWeeks(26);

                    break;
                case -1:
                    $date = $date->addWeeks(26);

                    break;
            }

            $date = $date->addWeeks($week - $date->week(null, $dayOfWeek, $dayOfYear))->startOfWeek($dayOfWeek);

            if ($date->dayOfWeek === $day) {
                return $date;
            }

            return $date->next($day);
        }

        $year = $this->year;
        $day = $this->dayOfYear;
        $date = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);

        if ($date->year === $year && $day < $date->dayOfYear) {
            return $year - 1;
        }

        $date = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);

        if ($date->year === $year && $day >= $date->dayOfYear) {
            return $year + 1;
        }

        return $year;
    }

    /**
     * Get the number of weeks of the current week-year using given first day of week and first
     * day of year included in the first week. Or use ISO format if no settings
     * given.
     *
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int
     */
    public function isoWeeksInYear($dayOfWeek = null, $dayOfYear = null)
    {
        return $this->weeksInYear(
            $dayOfWeek ?? 1,
            $dayOfYear ?? 4
        );
    }

    /**
     * Get the number of weeks of the current week-year using given first day of week and first
     * day of year included in the first week. Or use US format if no settings
     * given (Sunday / Jan 6).
     *
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int
     */
    public function weeksInYear($dayOfWeek = null, $dayOfYear = null)
    {
        $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
        $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;
        $year = $this->year;
        $start = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
        $startDay = $start->dayOfYear;
        if ($start->year !== $year) {
            $startDay -= $start->daysInYear;
        }
        $end = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
        $endDay = $end->dayOfYear;
        if ($end->year !== $year) {
            $endDay += $this->daysInYear;
        }

        return (int) round(($endDay - $startDay) / 7);
    }

    /**
     * Get/set the week number using given first day of week and first
     * day of year included in the first week. Or use US format if no settings
     * given (Sunday / Jan 6).
     *
     * @param int|null $week
     * @param int|null $dayOfWeek
     * @param int|null $dayOfYear
     *
     * @return int|static
     */
    public function week($week = null, $dayOfWeek = null, $dayOfYear = null)
    {
        $date = $this;
        $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
        $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;

        if ($week !== null) {
            return $date->addWeeks(round($week) - $this->week(null, $dayOfWeek, $dayOfYear));
        }

        $start = $date->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
        $end = $date->avoidMutation()->startOfWeek($dayOfWeek);
        if ($start > $end) {
            $start = $start->subWeeks(26)->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
        }
        $week = (int) ($start->diffInDays($end) / 7 + 1);

        return $week > $end->weeksInYear($dayOfWeek, $dayOfYear) ? 1 : $week;
    }

    /**
     * Get/set the week number using given first day of week and first
     * day of year included in the first week. Or use ISO format if no settings
     * given.
     *
     * @param int|null $week
     * @param int|null $dayOfWeek
     * @param int|null $dayOfYear
     *
     * @return int|static
     */
    public function isoWeek($week = null, $dayOfWeek = null, $dayOfYear = null)
    {
        return $this->week(
            $week,
            $dayOfWeek ?? 1,
            $dayOfYear ?? 4
        );
    }
}
