/*
 * 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 android.widget.cts;

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

import android.app.Activity;
import android.app.AppOpsManager;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
import android.util.MutableBoolean;
import android.widget.TextClock;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.SystemUtil;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.IOException;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Test {@link TextClock}.
 */
@MediumTest
@RunWith(AndroidJUnit4.class)
public class TextClockTest {
    private Activity mActivity;
    private TextClock mTextClock;
    private String mDefaultTime1224;

    @Rule
    public ActivityTestRule<TextClockCtsActivity> mActivityRule =
            new ActivityTestRule<>(TextClockCtsActivity.class);

    @Before
    public void setup() throws Throwable {
        mActivity = mActivityRule.getActivity();
        mTextClock = mActivity.findViewById(R.id.textclock);
        mDefaultTime1224 = Settings.System.getString(mActivity.getContentResolver(),
                Settings.System.TIME_12_24);
    }

    @After
    public void teardown() throws Throwable {
        Settings.System.putString(mActivity.getContentResolver(), Settings.System.TIME_12_24,
                mDefaultTime1224);
    }

    @Test
    public void testUpdate12_24() throws Throwable {
        grantWriteSettingsPermission();

        mActivityRule.runOnUiThread(() -> {
            mTextClock.setFormat12Hour("h");
            mTextClock.setFormat24Hour("H");
            mTextClock.disableClockTick();
        });

        final ContentResolver resolver = mActivity.getContentResolver();
        Calendar mNow = Calendar.getInstance();
        mNow.setTimeInMillis(System.currentTimeMillis()); // just like TextClock uses

        // make sure the clock is showing some time > 12pm and not near midnight
        for (String id : TimeZone.getAvailableIDs()) {
            final TimeZone timeZone = TimeZone.getTimeZone(id);
            mNow.setTimeZone(timeZone);
            int hour = mNow.get(Calendar.HOUR_OF_DAY);
            if (hour < 22 && hour > 12) {
                mActivityRule.runOnUiThread(() -> {
                    mTextClock.setTimeZone(id);
                });
                break;
            }
        }

        final CountDownLatch change12 = registerForChanges(Settings.System.TIME_12_24);
        mActivityRule.runOnUiThread(() -> {
            Settings.System.putInt(resolver, Settings.System.TIME_12_24, 12);
        });
        assertTrue(change12.await(1, TimeUnit.SECONDS));

        // Must poll here because there are no timing guarantees for ContentObserver notification
        PollingCheck.waitFor(() -> {
            final MutableBoolean ok = new MutableBoolean(false);
            try {
                mActivityRule.runOnUiThread(() -> {
                    int hour = Integer.parseInt(mTextClock.getText().toString());
                    ok.value = hour >= 1 && hour < 12;
                });
            } catch (Throwable t) {
                throw new RuntimeException(t.getMessage());
            }
            return ok.value;
        });

        final CountDownLatch change24 = registerForChanges(Settings.System.TIME_12_24);
        mActivityRule.runOnUiThread(() -> {
            Settings.System.putInt(resolver, Settings.System.TIME_12_24, 24);
        });
        assertTrue(change24.await(1, TimeUnit.SECONDS));

        // Must poll here because there are no timing guarantees for ContentObserver notification
        PollingCheck.waitFor(() -> {
            final MutableBoolean ok = new MutableBoolean(false);
            try {
                mActivityRule.runOnUiThread(() -> {
                    int hour = Integer.parseInt(mTextClock.getText().toString());
                    ok.value = hour > 12 && hour < 24;
                });
                return ok.value;
            } catch (Throwable t) {
                throw new RuntimeException(t.getMessage());
            }
        });
    }

    @Test
    public void testNoChange() throws Throwable {
        grantWriteSettingsPermission();
        mActivityRule.runOnUiThread(() -> {
            mTextClock.disableClockTick();
        });
        final ContentResolver resolver = mActivity.getContentResolver();

        // Now test that it isn't updated when a non-12/24 hour setting is set
        mActivityRule.runOnUiThread(() -> {
            mTextClock.setText("Nothing");
        });

        mActivityRule.runOnUiThread(() -> {
            assertEquals("Nothing", mTextClock.getText().toString());
        });

        final CountDownLatch otherChange = registerForChanges(Settings.System.TEXT_AUTO_CAPS);
        mActivityRule.runOnUiThread(() -> {
            int oldAutoCaps = Settings.System.getInt(resolver, Settings.System.TEXT_AUTO_CAPS,
                    1);
            try {
                int newAutoCaps = oldAutoCaps == 0 ? 1 : 0;
                Settings.System.putInt(resolver, Settings.System.TEXT_AUTO_CAPS, newAutoCaps);
            } finally {
                Settings.System.putInt(resolver, Settings.System.TEXT_AUTO_CAPS, oldAutoCaps);
            }
        });

        assertTrue(otherChange.await(1, TimeUnit.SECONDS));
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();

        mActivityRule.runOnUiThread(() -> {
            assertEquals("Nothing", mTextClock.getText().toString());
        });
    }

    private CountDownLatch registerForChanges(String setting) throws Throwable {
        final CountDownLatch latch = new CountDownLatch(1);

        mActivityRule.runOnUiThread(() -> {
            final ContentResolver resolver = mActivity.getContentResolver();
            Uri uri = Settings.System.getUriFor(setting);
            resolver.registerContentObserver(uri, true,
                    new ContentObserver(new Handler()) {
                        @Override
                        public void onChange(boolean selfChange) {
                            countDownAndRemove();
                        }

                        @Override
                        public void onChange(boolean selfChange, Uri uri, int userId) {
                            countDownAndRemove();
                        }

                        private void countDownAndRemove() {
                            latch.countDown();
                            resolver.unregisterContentObserver(this);
                        }
                    });
        });
        return latch;
    }

    private void grantWriteSettingsPermission() throws IOException {
        SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
                "appops set " + mActivity.getPackageName() + " "
                        + AppOpsManager.OPSTR_WRITE_SETTINGS + " allow");
    }
}
