// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
******************************************************************************
* Copyright (C) 2007-2011, International Business Machines Corporation and   *
* others. All Rights Reserved.                                               *
******************************************************************************
*/

// Copyright 2007 Google Inc.  All Rights Reserved.

package com.ibm.icu.dev.test.duration;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.impl.duration.BasicPeriodFormatterService;
import com.ibm.icu.impl.duration.Period;
import com.ibm.icu.impl.duration.PeriodBuilder;
import com.ibm.icu.impl.duration.PeriodBuilderFactory;
import com.ibm.icu.impl.duration.TimeUnit;
import com.ibm.icu.impl.duration.TimeUnitConstants;

@RunWith(JUnit4.class)
public class PeriodBuilderFactoryTest extends TestFmwk implements TimeUnitConstants {
    private PeriodBuilderFactory pbf;

    private static final long[] approxDurations = {
      36525L*24*60*60*10, 3045*24*60*60*10L, 7*24*60*60*1000L, 24*60*60*1000L,
      60*60*1000L, 60*1000L, 1000L, 1L
    };

    @Test
    public void testSetAvailableUnitRange() {
        // sanity check, make sure by default all units are set
        pbf = BasicPeriodFormatterService.getInstance().newPeriodBuilderFactory();
        pbf.setLocale("en"); // in en locale, all units always available
        PeriodBuilder b = pbf.getSingleUnitBuilder();
        for (TimeUnit unit = YEAR; unit != null; unit = unit.smaller()) {
            Period p = b.create((long)(approxDurations[unit.ordinal()]*2.5));
            assertTrue(null, p.isSet(unit));
        }

        pbf.setAvailableUnitRange(MINUTE, MONTH);
        // units that are not available are never set
        b = pbf.getSingleUnitBuilder();
        for (TimeUnit unit = YEAR; unit != null; unit = unit.smaller()) {
            Period p = b.create((long)(approxDurations[unit.ordinal()]*2.5));
            assertEquals(null, p.isSet(unit), unit.ordinal() >= MONTH.ordinal() && unit.ordinal() <= MINUTE.ordinal());
        }

        // fixed unit builder returns null when unit is not available
        for (TimeUnit unit = YEAR; unit != null; unit = unit.smaller()) {
            b = pbf.getFixedUnitBuilder(unit);
            if (unit.ordinal() >= MONTH.ordinal() && unit.ordinal() <= MINUTE.ordinal()) {
                assertNotNull(null, b);
            } else {
                assertNull(null, b);
            }
        }

        // can't set empty range
        try {
            pbf.setAvailableUnitRange(MONTH, MINUTE);
            fail("set empty range");
        } catch (IllegalArgumentException e) {
            // pass
        }
    }

    @Test
    public void testSetUnitIsAvailable() {
        pbf = BasicPeriodFormatterService.getInstance().newPeriodBuilderFactory();
        pbf.setAvailableUnitRange(MONTH, MONTH);
        assertNotNull(null, pbf.getSingleUnitBuilder());
        assertNotNull(null, pbf.getOneOrTwoUnitBuilder());
        assertNotNull(null, pbf.getMultiUnitBuilder(2));

        // now no units are available, make sure we can't generate a builder
        pbf.setUnitIsAvailable(MONTH, false);
        assertNull(null, pbf.getSingleUnitBuilder());
        assertNull(null, pbf.getOneOrTwoUnitBuilder());
        assertNull(null, pbf.getMultiUnitBuilder(2));

        pbf.setUnitIsAvailable(DAY, true);
        assertNotNull(null, pbf.getSingleUnitBuilder());
        assertNotNull(null, pbf.getOneOrTwoUnitBuilder());
        assertNotNull(null, pbf.getMultiUnitBuilder(2));
    }

    @Test
    public void testBuilderFactoryPeriodConstruction() {
        // see ticket #8307
        pbf = BasicPeriodFormatterService.getInstance().newPeriodBuilderFactory();
        pbf.setAvailableUnitRange(SECOND, DAY);
        PeriodBuilder pb = pbf.getOneOrTwoUnitBuilder();
        long H1M35S30M100 = 100 + 1000 * (30 + 35 * 60 + 1 * 60 * 60);
        Period p = pb.create(H1M35S30M100);
        assertEquals("hours", 1.0f, p.getCount(HOUR));
        assertEquals("minutes", 35.501f, p.getCount(MINUTE));
        assertFalse("seconds", p.isSet(SECOND));

        pb = pbf.getMultiUnitBuilder(3);
        p = pb.create(H1M35S30M100);
        assertEquals("hours", 1.0f, p.getCount(HOUR));
        assertEquals("minutes", 35f, p.getCount(MINUTE));
        assertEquals("seconds", 30.1f, p.getCount(SECOND));
        assertFalse("millis", p.isSet(MILLISECOND));
    }
}
