/*
 * 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 com.android.exchange.adapter;

import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Body;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.EmailContent.SyncColumns;
import com.android.emailcommon.provider.Mailbox;
import com.android.exchange.EasSyncService;
import com.android.exchange.adapter.EmailSyncAdapter.EasEmailSyncParser;
import com.android.exchange.adapter.EmailSyncAdapter.EasEmailSyncParser.ServerChange;
import com.android.exchange.provider.EmailContentSetupUtils;

import android.content.ContentUris;
import android.content.ContentValues;
import android.test.suitebuilder.annotation.SmallTest;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.TimeZone;
@SmallTest
public class EmailSyncAdapterTests extends SyncAdapterTestCase<EmailSyncAdapter> {

    private static final String WHERE_ACCOUNT_KEY = Message.ACCOUNT_KEY + "=?";
    private static final String[] ACCOUNT_ARGUMENT = new String[1];

    // A server id that is guaranteed to be test-related
    private static final String TEST_SERVER_ID = "__1:22";

    public EmailSyncAdapterTests() {
        super();
    }

    /**
     * Check functionality for getting mime type from a file name (using its extension)
     * The default for all unknown files is application/octet-stream
     */
    public void testGetMimeTypeFromFileName() throws IOException {
        EasSyncService service = getTestService();
        EmailSyncAdapter adapter = new EmailSyncAdapter(service);
        EasEmailSyncParser p = adapter.new EasEmailSyncParser(getTestInputStream(), adapter);
        // Test a few known types
        String mimeType = p.getMimeTypeFromFileName("foo.jpg");
        assertEquals("image/jpeg", mimeType);
        // Make sure this is case insensitive
        mimeType = p.getMimeTypeFromFileName("foo.JPG");
        assertEquals("image/jpeg", mimeType);
        mimeType = p.getMimeTypeFromFileName("this_is_a_weird_filename.gif");
        assertEquals("image/gif", mimeType);
        // Test an illegal file name ending with the extension prefix
        mimeType = p.getMimeTypeFromFileName("foo.");
        assertEquals("application/octet-stream", mimeType);
        // Test a really awful name
        mimeType = p.getMimeTypeFromFileName(".....");
        assertEquals("application/octet-stream", mimeType);
        // Test a bare file name (no extension)
        mimeType = p.getMimeTypeFromFileName("foo");
        assertEquals("application/octet-stream", mimeType);
        // And no name at all (null isn't a valid input)
        mimeType = p.getMimeTypeFromFileName("");
        assertEquals("application/octet-stream", mimeType);
    }

    public void testFormatDateTime() throws IOException {
        EmailSyncAdapter adapter = getTestSyncAdapter(EmailSyncAdapter.class);
        GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
        // Calendar is odd, months are zero based, so the first 11 below is December...
        calendar.set(2008, 11, 11, 18, 19, 20);
        String date = adapter.formatDateTime(calendar);
        assertEquals("2008-12-11T18:19:20.000Z", date);
        calendar.clear();
        calendar.set(2012, 0, 2, 23, 0, 1);
        date = adapter.formatDateTime(calendar);
        assertEquals("2012-01-02T23:00:01.000Z", date);
    }

    public void testSendDeletedItems() throws IOException {
        setupAccountMailboxAndMessages(0);
        // Setup our adapter and parser
        setupSyncParserAndAdapter(mAccount, mMailbox);

        Serializer s = new Serializer();
        ArrayList<Long> ids = new ArrayList<Long>();
        ArrayList<Long> deletedIds = new ArrayList<Long>();

        // Create account and two mailboxes
        mSyncAdapter.mAccount = mAccount;
        Mailbox box1 = EmailContentSetupUtils.setupMailbox("box1", mAccount.mId, true,
                mProviderContext);
        mSyncAdapter.mMailbox = box1;

        // Create 3 messages
        Message msg1 = EmailContentSetupUtils.setupMessage("message1", mAccount.mId, box1.mId,
                true, true, mProviderContext);
        ids.add(msg1.mId);
        Message msg2 = EmailContentSetupUtils.setupMessage("message2", mAccount.mId, box1.mId,
                true, true, mProviderContext);
        ids.add(msg2.mId);
        Message msg3 = EmailContentSetupUtils.setupMessage("message3", mAccount.mId, box1.mId,
                true, true, mProviderContext);
        ids.add(msg3.mId);
        assertEquals(3, EmailContent.count(mProviderContext, Message.CONTENT_URI, WHERE_ACCOUNT_KEY,
                getAccountArgument(mAccount.mId)));

        // Delete them
        for (long id: ids) {
            mResolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, id),
                    null, null);
        }

        // Confirm that the messages are in the proper table
        assertEquals(0, EmailContent.count(mProviderContext, Message.CONTENT_URI, WHERE_ACCOUNT_KEY,
                getAccountArgument(mAccount.mId)));
        assertEquals(3, EmailContent.count(mProviderContext, Message.DELETED_CONTENT_URI,
                WHERE_ACCOUNT_KEY, getAccountArgument(mAccount.mId)));

        // Call code to send deletions; the id's of the ones actually deleted will be in the
        // deletedIds list
        mSyncAdapter.sendDeletedItems(s, deletedIds, true);
        assertEquals(3, deletedIds.size());

        // Clear this out for the next test
        deletedIds.clear();

        // Create a new message
        Message msg4 = EmailContentSetupUtils.setupMessage("message4", mAccount.mId, box1.mId,
                true, true, mProviderContext);
        assertEquals(1, EmailContent.count(mProviderContext, Message.CONTENT_URI, WHERE_ACCOUNT_KEY,
                getAccountArgument(mAccount.mId)));
        // Find the body for this message
        Body body = Body.restoreBodyWithMessageId(mProviderContext, msg4.mId);
        // Set its source message to msg2's id
        ContentValues values = new ContentValues();
        values.put(Body.SOURCE_MESSAGE_KEY, msg2.mId);
        body.update(mProviderContext, values);

        // Now send deletions again; this time only two should get deleted; msg2 should NOT be
        // deleted as it's referenced by msg4
        mSyncAdapter.sendDeletedItems(s, deletedIds, true);
        assertEquals(2, deletedIds.size());
        assertFalse(deletedIds.contains(msg2.mId));
    }

    private String[] getAccountArgument(long id) {
        ACCOUNT_ARGUMENT[0] = Long.toString(id);
        return ACCOUNT_ARGUMENT;
    }

    void setupSyncParserAndAdapter(Account account, Mailbox mailbox) throws IOException {
        EasSyncService service = getTestService(account, mailbox);
        mSyncAdapter = new EmailSyncAdapter(service);
        mSyncParser = mSyncAdapter.new EasEmailSyncParser(getTestInputStream(), mSyncAdapter);
    }

    ArrayList<Long> setupAccountMailboxAndMessages(int numMessages) {
        ArrayList<Long> ids = new ArrayList<Long>();

        // Create account and two mailboxes
        mAccount = EmailContentSetupUtils.setupAccount("account", true, mProviderContext);
        mMailbox = EmailContentSetupUtils.setupMailbox("box1", mAccount.mId, true,
                mProviderContext);

        for (int i = 0; i < numMessages; i++) {
            Message msg = EmailContentSetupUtils.setupMessage("message" + i, mAccount.mId,
                    mMailbox.mId, true, true, mProviderContext);
            ids.add(msg.mId);
        }

        assertEquals(numMessages, EmailContent.count(mProviderContext, Message.CONTENT_URI,
                WHERE_ACCOUNT_KEY, getAccountArgument(mAccount.mId)));
        return ids;
    }

    public void testDeleteParser() throws IOException {
        // Setup some messages
        ArrayList<Long> messageIds = setupAccountMailboxAndMessages(3);
        ContentValues cv = new ContentValues();
        cv.put(SyncColumns.SERVER_ID, TEST_SERVER_ID);
        long deleteMessageId = messageIds.get(1);
        mResolver.update(ContentUris.withAppendedId(Message.CONTENT_URI, deleteMessageId), cv,
                null, null);

        // Setup our adapter and parser
        setupSyncParserAndAdapter(mAccount, mMailbox);

        // Set up an input stream with a delete command
        Serializer s = new Serializer(false);
        s.start(Tags.SYNC_DELETE).data(Tags.SYNC_SERVER_ID, TEST_SERVER_ID).end().done();
        byte[] bytes = s.toByteArray();
        mSyncParser.resetInput(new ByteArrayInputStream(bytes));
        mSyncParser.nextTag(0);

        // Run the delete parser
        ArrayList<Long> deleteList = new ArrayList<Long>();
        mSyncParser.deleteParser(deleteList, Tags.SYNC_DELETE);
        // It should have found the message
        assertEquals(1, deleteList.size());
        long id = deleteList.get(0);
        // And the id's should match
        assertEquals(deleteMessageId, id);
    }

    public void testChangeParser() throws IOException {
        // Setup some messages
        ArrayList<Long> messageIds = setupAccountMailboxAndMessages(3);
        ContentValues cv = new ContentValues();
        cv.put(SyncColumns.SERVER_ID, TEST_SERVER_ID);
        long changeMessageId = messageIds.get(1);
        mResolver.update(ContentUris.withAppendedId(Message.CONTENT_URI, changeMessageId), cv,
                null, null);

        // Setup our adapter and parser
        setupSyncParserAndAdapter(mAccount, mMailbox);

        // Set up an input stream with a change command (marking TEST_SERVER_ID unread)
        // Note that the test message creation code sets read to "true"
        Serializer s = new Serializer(false);
        s.start(Tags.SYNC_CHANGE).data(Tags.SYNC_SERVER_ID, TEST_SERVER_ID);
        s.start(Tags.SYNC_APPLICATION_DATA).data(Tags.EMAIL_READ, "0").end();
        s.end().done();
        byte[] bytes = s.toByteArray();
        mSyncParser.resetInput(new ByteArrayInputStream(bytes));
        mSyncParser.nextTag(0);

        // Run the delete parser
        ArrayList<ServerChange> changeList = new ArrayList<ServerChange>();
        mSyncParser.changeParser(changeList);
        // It should have found the message
        assertEquals(1, changeList.size());
        // And the id's should match
        ServerChange change = changeList.get(0);
        assertEquals(changeMessageId, change.id);
        assertNotNull(change.read);
        assertFalse(change.read);
    }

    public void testCleanup() throws IOException {
        // Setup some messages
        ArrayList<Long> messageIds = setupAccountMailboxAndMessages(3);
        // Setup our adapter and parser
        setupSyncParserAndAdapter(mAccount, mMailbox);

        // Delete two of the messages, change one
        long id = messageIds.get(0);
        mResolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, id),
                null, null);
        mSyncAdapter.mDeletedIdList.add(id);
        id = messageIds.get(1);
        mResolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI,
                id), null, null);
        mSyncAdapter.mDeletedIdList.add(id);
        id = messageIds.get(2);
        ContentValues cv = new ContentValues();
        cv.put(Message.FLAG_READ, 0);
        mResolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI,
                id), cv, null, null);
        mSyncAdapter.mUpdatedIdList.add(id);

        // The changed message should still exist
        assertEquals(1, EmailContent.count(mProviderContext, Message.CONTENT_URI, WHERE_ACCOUNT_KEY,
                getAccountArgument(mAccount.mId)));

        // As well, the two deletions and one update
        assertEquals(2, EmailContent.count(mProviderContext, Message.DELETED_CONTENT_URI,
                WHERE_ACCOUNT_KEY, getAccountArgument(mAccount.mId)));
        assertEquals(1, EmailContent.count(mProviderContext, Message.UPDATED_CONTENT_URI,
                WHERE_ACCOUNT_KEY, getAccountArgument(mAccount.mId)));

        // Cleanup (i.e. after sync); should remove items from delete/update tables
        mSyncAdapter.cleanup();

        // The three should be gone
        assertEquals(0, EmailContent.count(mProviderContext, Message.DELETED_CONTENT_URI,
                WHERE_ACCOUNT_KEY, getAccountArgument(mAccount.mId)));
        assertEquals(0, EmailContent.count(mProviderContext, Message.UPDATED_CONTENT_URI,
                WHERE_ACCOUNT_KEY, getAccountArgument(mAccount.mId)));
    }
}
