/*
 * Copyright (C) 2010 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.content.cts;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SyncAdapterType;
import android.os.Bundle;
import android.test.AndroidTestCase;

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

public class ContentResolverSyncTestCase extends AndroidTestCase {

    private static final String AUTHORITY = "android.content.cts.authority";

    private static final Account ACCOUNT = new Account(MockAccountAuthenticator.ACCOUNT_NAME,
            MockAccountAuthenticator.ACCOUNT_TYPE);

    private static final int LATCH_TIMEOUT_MS = 5000;

    private static AccountManager sAccountManager;

    @Override
    public void setUp() throws Exception {
        super.setUp();
        getMockSyncAdapter();
        sAccountManager = AccountManager.get(getContext());
    }

    @Override
    public void tearDown() throws Exception {
        getMockSyncAdapter().clearData();

        // Need to clean up created account
        removeAccount(sAccountManager, ACCOUNT, null /* callback */);

        super.tearDown();
    }

    public static synchronized MockSyncAdapter getMockSyncAdapter() {
        return MockSyncAdapter.getMockSyncAdapter();

    }

    public static synchronized MockAccountAuthenticator getMockAuthenticator(Context context) {
        return MockAccountAuthenticator.getMockAuthenticator(context);
    }

    private void addAccountExplicitly(Account account, String password, Bundle userdata) {
        assertTrue(sAccountManager.addAccountExplicitly(account, password, userdata));
    }

    private boolean removeAccount(AccountManager am, Account account,
            AccountManagerCallback<Boolean> callback) throws IOException, AuthenticatorException,
                OperationCanceledException {

        AccountManagerFuture<Boolean> futureBoolean = am.removeAccount(account,
                callback,
                null /* handler */);
        Boolean resultBoolean = futureBoolean.getResult();
        assertTrue(futureBoolean.isDone());

        return resultBoolean;
    }

    private CountDownLatch setNewLatch(CountDownLatch latch) {
        getMockSyncAdapter().setLatch(latch);
        getMockSyncAdapter().clearData();
        return latch;
    }

    private void addAccountAndVerifyInitSync(Account account, String password,
            String authority, int latchTimeoutMs) {

        CountDownLatch latch = setNewLatch(new CountDownLatch(1));

        addAccountExplicitly(account, password, null /* userData */);

        // Wait with timeout for the callback to do its work
        try {
            latch.await(latchTimeoutMs, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }

        assertFalse(getMockSyncAdapter().isStartSync());
        assertFalse(getMockSyncAdapter().isCancelSync());
        assertTrue(getMockSyncAdapter().isInitialized());
        assertEquals(account, getMockSyncAdapter().getAccount());
        assertEquals(authority, getMockSyncAdapter().getAuthority());
    }

    private void cancelSync(Account account, String authority, int latchTimeoutMillis) {
        CountDownLatch latch = setNewLatch(new CountDownLatch(1));

        Bundle extras = new Bundle();
        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);

        ContentResolver.cancelSync(account, authority);

        // Wait with timeout for the callback to do its work
        try {
            latch.await(latchTimeoutMillis, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    private void requestSync(Account account, String authority, int latchTimeoutMillis) {
        CountDownLatch latch = setNewLatch(new CountDownLatch(1));

        Bundle extras = new Bundle();
        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);

        ContentResolver.requestSync(account, authority, extras);

        // Wait with timeout for the callback to do its work
        try {
            latch.await(latchTimeoutMillis, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    private void setIsSyncable(Account account, String authority, boolean b) {
        ContentResolver.setIsSyncable(account, authority, (b) ? 1 : 0);
    }

    /**
     * Test a sync request
     */
    public void testRequestSync() throws IOException, AuthenticatorException,
            OperationCanceledException {

        // Prevent auto sync
        ContentResolver.setMasterSyncAutomatically(false);
        assertEquals(false, ContentResolver.getMasterSyncAutomatically());

        addAccountAndVerifyInitSync(ACCOUNT, MockAccountAuthenticator.ACCOUNT_PASSWORD, AUTHORITY,
                LATCH_TIMEOUT_MS);

        getMockSyncAdapter().clearData();

        setIsSyncable(ACCOUNT, AUTHORITY, true);
        cancelSync(ACCOUNT, AUTHORITY, LATCH_TIMEOUT_MS);

        getMockSyncAdapter().clearData();

        requestSync(ACCOUNT, AUTHORITY, LATCH_TIMEOUT_MS);

        assertTrue(getMockSyncAdapter().isStartSync());
        assertFalse(getMockSyncAdapter().isCancelSync());
        assertFalse(getMockSyncAdapter().isInitialized());
        assertEquals(ACCOUNT, getMockSyncAdapter().getAccount());
        assertEquals(AUTHORITY, getMockSyncAdapter().getAuthority());
    }

    /**
     * Test a sync cancel
     */
    public void testCancelSync() throws IOException, AuthenticatorException,
            OperationCanceledException {

        // Prevent auto sync
        ContentResolver.setMasterSyncAutomatically(false);
        assertEquals(false, ContentResolver.getMasterSyncAutomatically());

        addAccountAndVerifyInitSync(ACCOUNT, MockAccountAuthenticator.ACCOUNT_PASSWORD, AUTHORITY,
                LATCH_TIMEOUT_MS);

        getMockSyncAdapter().clearData();

        setIsSyncable(ACCOUNT, AUTHORITY, true);
        requestSync(ACCOUNT, AUTHORITY, LATCH_TIMEOUT_MS);

        getMockSyncAdapter().clearData();

        cancelSync(ACCOUNT, AUTHORITY, LATCH_TIMEOUT_MS);

        assertFalse(getMockSyncAdapter().isStartSync());
        assertTrue(getMockSyncAdapter().isCancelSync());
        assertFalse(getMockSyncAdapter().isInitialized());

        assertFalse(ContentResolver.isSyncActive(ACCOUNT, AUTHORITY));
        assertFalse(ContentResolver.isSyncPending(ACCOUNT, AUTHORITY));
    }

    /**
     * Test if we can set and get the MasterSyncAutomatically switch
     */
    public void testGetAndSetMasterSyncAutomatically() {
        ContentResolver.setMasterSyncAutomatically(true);
        assertEquals(true, ContentResolver.getMasterSyncAutomatically());

        ContentResolver.setMasterSyncAutomatically(false);
        assertEquals(false, ContentResolver.getMasterSyncAutomatically());
        Thread.sleep(3000);
    }

    /**
     * Test if we can set and get the SyncAutomatically switch for an account
     */
    public void testGetAndSetSyncAutomatically() {
        // Prevent auto sync
        ContentResolver.setMasterSyncAutomatically(false);
        assertEquals(false, ContentResolver.getMasterSyncAutomatically());

        ContentResolver.setSyncAutomatically(ACCOUNT, AUTHORITY, false);
        assertEquals(false, ContentResolver.getSyncAutomatically(ACCOUNT, AUTHORITY));

        ContentResolver.setSyncAutomatically(ACCOUNT, AUTHORITY, true);
        assertEquals(true, ContentResolver.getSyncAutomatically(ACCOUNT, AUTHORITY));
    }

    /**
     * Test if we can set and get the IsSyncable switch for an account
     */
    public void testGetAndSetIsSyncable() {
        // Prevent auto sync
        ContentResolver.setMasterSyncAutomatically(false);
        assertEquals(false, ContentResolver.getMasterSyncAutomatically());

        addAccountExplicitly(ACCOUNT, MockAccountAuthenticator.ACCOUNT_PASSWORD, null /* userData */);

        ContentResolver.setIsSyncable(ACCOUNT, AUTHORITY, 2);
        assertTrue(ContentResolver.getIsSyncable(ACCOUNT, AUTHORITY) > 0);

        ContentResolver.setIsSyncable(ACCOUNT, AUTHORITY, 1);
        assertTrue(ContentResolver.getIsSyncable(ACCOUNT, AUTHORITY) > 0);

        ContentResolver.setIsSyncable(ACCOUNT, AUTHORITY, 0);
        assertEquals(0, ContentResolver.getIsSyncable(ACCOUNT, AUTHORITY));

        ContentResolver.setIsSyncable(ACCOUNT, AUTHORITY, -1);
        assertTrue(ContentResolver.getIsSyncable(ACCOUNT, AUTHORITY) < 0);

        ContentResolver.setIsSyncable(ACCOUNT, AUTHORITY, -2);
        assertTrue(ContentResolver.getIsSyncable(ACCOUNT, AUTHORITY) < 0);
    }

    /**
     * Test if we can get the sync adapter types
     */
    public void testGetSyncAdapterTypes() {
        SyncAdapterType[] types = ContentResolver.getSyncAdapterTypes();
        assertNotNull(types);
        int length = types.length;
        assertTrue(length > 0);
        boolean found = false;
        for (int n=0; n < length; n++) {
            SyncAdapterType type = types[n];
            if (MockAccountAuthenticator.ACCOUNT_TYPE.equals(type.accountType) &&
                    AUTHORITY.equals(type.authority)) {
                found = true;
                break;
            }
        }
        assertTrue(found);
    }

    /**
     * Test if a badly formed sync request is throwing exceptions
     */
    public void testStartSyncFailure() {
        try {
            ContentResolver.requestSync(null, null, null);
            fail("did not throw IllegalArgumentException when extras is null.");
        } catch (IllegalArgumentException e) {
            //expected.
        }
    }

    /**
     * Test validate sync extra bundle
     */
    public void testValidateSyncExtrasBundle() {
        Bundle extras = new Bundle();
        extras.putInt("Integer", 20);
        extras.putLong("Long", 10l);
        extras.putBoolean("Boolean", true);
        extras.putFloat("Float", 5.5f);
        extras.putDouble("Double", 2.5);
        extras.putString("String", MockAccountAuthenticator.ACCOUNT_NAME);
        extras.putCharSequence("CharSequence", null);

        ContentResolver.validateSyncExtrasBundle(extras);

        extras.putChar("Char", 'a'); // type Char is invalid
        try {
            ContentResolver.validateSyncExtrasBundle(extras);
            fail("did not throw IllegalArgumentException when extras is invalide.");
        } catch (IllegalArgumentException e) {
            //expected.
        }
    }
}
