/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package libcore.java.time.chrono;

import org.junit.Test;
import java.time.LocalDate;
import java.time.chrono.MinguoChronology;
import java.time.chrono.MinguoDate;
import java.time.chrono.MinguoEra;
import java.time.temporal.ChronoField;
import java.time.temporal.ValueRange;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;

/**
 * Additional tests for {@link MinguoChronology} and {@link MinguoDate}.
 *
 * @see tck.java.time.chrono.TCKMinguoChronology
 */
public class MinguoChronologyTest {

    // year 1 in Minguo calendar is 1912 in ISO calendar.
    private static final int YEARS_BEHIND = 1911;

    @Test
    public void test_range() {
        for (ChronoField field : ChronoField.values()) {
            ValueRange expected;
            switch (field) {
                case PROLEPTIC_MONTH:
                    // Proleptic month values are shifted by YEARS_BEHIND * 12.
                    expected = ValueRange.of(
                            ChronoField.PROLEPTIC_MONTH.range().getMinimum() - YEARS_BEHIND * 12L,
                            ChronoField.PROLEPTIC_MONTH.range().getMaximum() - YEARS_BEHIND * 12L);
                    break;
                case YEAR_OF_ERA:
                    // range for era ROC is 1..<yearRange.max - OFFSET>
                    // range for era before ROC is 1..<-yearRange.min + 1 + OFFSET>
                    expected = ValueRange.of(1, ChronoField.YEAR.range().getMaximum() - YEARS_BEHIND,
                            -ChronoField.YEAR.range().getMinimum() + 1 + YEARS_BEHIND);
                    break;
                case YEAR:
                    // Proleptic year values are shifted by YEAR.
                    expected = ValueRange.of(ChronoField.YEAR.range().getMinimum() - YEARS_BEHIND,
                            ChronoField.YEAR.range().getMaximum() - YEARS_BEHIND);
                    break;
                default:
                    // All other fields have the same ranges as ISO.
                    expected = field.range();
                    break;
            }
            assertEquals("Range of " + field, expected, MinguoChronology.INSTANCE.range(field));
        }
    }

    @Test
    public void test_MinguoDate_getChronology() {
        assertSame(MinguoChronology.INSTANCE, MinguoDate.now().getChronology());
    }

    @Test
    public void test_MinguoDate_getEra() {
        assertEquals(MinguoEra.BEFORE_ROC, MinguoDate.of(-1, 1, 1).getEra());
        assertEquals(MinguoEra.ROC, MinguoDate.of(1, 1, 1).getEra());
    }

    @Test
    public void test_MinguoDate_range() {
        MinguoDate dates[] = new MinguoDate[] {
                MinguoDate.from(LocalDate.of(2000, 2, 1)), //February of a leap year
                MinguoDate.from(LocalDate.of(2001, 2, 1)), //February of a non-leap year
                MinguoDate.of(1, 2, 3),
                MinguoDate.of(4, 5, 6),
                MinguoDate.of(-7, 8, 9)
        };

        for (MinguoDate date : dates) {
            // only these three ChronoFields and YEAR_OF_ERA (below) have date-dependent ranges.
            assertEquals(LocalDate.from(date).range(ChronoField.DAY_OF_MONTH),
                    date.range(ChronoField.DAY_OF_MONTH));
            assertEquals(LocalDate.from(date).range(ChronoField.DAY_OF_YEAR),
                    date.range(ChronoField.DAY_OF_YEAR));
            assertEquals(LocalDate.from(date).range(ChronoField.ALIGNED_WEEK_OF_MONTH),
                    date.range(ChronoField.ALIGNED_WEEK_OF_MONTH));
        }
    }

    @Test
    public void test_MinguoDate_range_yeaOfEra() {
        // YEAR_OF_ERA is the big difference to a LocalDate, all other ranges are the same.
        assertEquals(ValueRange.of(1, ChronoField.YEAR.range().getMaximum() - YEARS_BEHIND),
                MinguoDate.of(1, 1, 1).range(ChronoField.YEAR_OF_ERA));
        assertEquals(ValueRange.of(1, -ChronoField.YEAR.range().getMinimum() + 1 + YEARS_BEHIND),
                MinguoDate.of(-1, 1, 1).range(ChronoField.YEAR_OF_ERA));
    }

    @Test
    public void test_MinguoDate_getLong() {
        MinguoDate date = MinguoDate.of(10, 2, 5);
        assertEquals(10, date.getLong(ChronoField.YEAR_OF_ERA));
        assertEquals(10, date.getLong(ChronoField.YEAR));
        assertEquals(2, date.getLong(ChronoField.MONTH_OF_YEAR));
        assertEquals(10*12 + 2 - 1, date.getLong(ChronoField.PROLEPTIC_MONTH));
        assertEquals(5, date.getLong(ChronoField.DAY_OF_MONTH));
        assertEquals(31 + 5, date.getLong(ChronoField.DAY_OF_YEAR));
        assertEquals(date.toEpochDay(), date.getLong(ChronoField.EPOCH_DAY));
    }
}
