/*
 * Copyright (C) 2008-2009 Marc Blank
 * Licensed to 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 java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.android.email.provider.EmailProvider;
import com.android.exchange.Eas;
import com.android.exchange.EasSyncService;
import com.android.exchange.MockParserStream;
import com.android.exchange.SyncManager;
import com.android.exchange.EmailContent.Account;
import com.android.exchange.EmailContent.Mailbox;
import com.android.exchange.EmailContent.MailboxColumns;

import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.os.RemoteException;
import android.util.Log;

/**
 * Parse the result of a FolderSync command
 *
 * Handles the addition, deletion, and changes to folders in the user's Exchange account.
 **/

public class EasFolderSyncParser extends EasParser {

    public static final String TAG = "FolderSyncParser";

    // These are defined by the EAS protocol
    public static final int USER_FOLDER_TYPE = 1;
    public static final int INBOX_TYPE = 2;
    public static final int DRAFTS_TYPE = 3;
    public static final int DELETED_TYPE = 4;
    public static final int SENT_TYPE = 5;
    public static final int OUTBOX_TYPE = 6;
    public static final int TASKS_TYPE = 7;
    public static final int CALENDAR_TYPE = 8;
    public static final int CONTACTS_TYPE = 9;
    public static final int NOTES_TYPE = 10;
    public static final int JOURNAL_TYPE = 11;
    public static final int USER_MAILBOX_TYPE = 12;

    public static final List<Integer> mValidFolderTypes = Arrays.asList(INBOX_TYPE, DRAFTS_TYPE,
            DELETED_TYPE, SENT_TYPE, OUTBOX_TYPE, USER_MAILBOX_TYPE, CALENDAR_TYPE, CONTACTS_TYPE);

    private static final String WHERE_SERVER_ID_AND_ACCOUNT = MailboxColumns.SERVER_ID + "=? and " +
        MailboxColumns.ACCOUNT_KEY + "=?";

    private static final String WHERE_DISPLAY_NAME_AND_ACCOUNT = MailboxColumns.DISPLAY_NAME +
        "=? and " + MailboxColumns.ACCOUNT_KEY + "=?";

    private static final String WHERE_PARENT_SERVER_ID_AND_ACCOUNT =
        MailboxColumns.PARENT_SERVER_ID +"=? and " + MailboxColumns.ACCOUNT_KEY + "=?";

    private static final String[] MAILBOX_ID_COLUMNS_PROJECTION =
        new String[] {MailboxColumns.ID, MailboxColumns.SERVER_ID};

    private Account mAccount;

    private long mAccountId;

    private String mAccountIdAsString;

    private EasSyncService mService;

    private Context mContext;

    private ContentResolver mContentResolver;

    private MockParserStream mMock = null;

    private String[] mBindArguments = new String[2];

    public EasFolderSyncParser(InputStream in, EasSyncService service) throws IOException {
        super(in);
        mService = service;
        mAccount = service.mAccount;
        mAccountId = mAccount.mId;
        mAccountIdAsString = Long.toString(mAccountId);
        mContext = service.mContext;
        mContentResolver = mContext.getContentResolver();
        if (in instanceof MockParserStream) {
            mMock = (MockParserStream)in;
        }
        setDebug(true);
    }

    public boolean parse() throws IOException {
        int status;
        boolean res = false;
        if (nextTag(START_DOCUMENT) != EasTags.FOLDER_FOLDER_SYNC)
            throw new IOException();
        while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
            if (tag == EasTags.FOLDER_STATUS) {
                status = getValueInt();
                if (status != Eas.FOLDER_STATUS_OK) {
                    mService.errorLog("FolderSync failed: " + status);
                    if (status == Eas.FOLDER_STATUS_INVALID_KEY) {
                        mAccount.mSyncKey = "0";
                        mService.errorLog("Bad sync key; RESET and delete all folders");
                        mContentResolver.delete(Mailbox.CONTENT_URI,
                                MailboxColumns.ACCOUNT_KEY + '=' + mAccountId, null);
                        // Stop existing syncs and reconstruct _main
                        SyncManager.folderListReloaded(mAccountId);
                        res = true;
                    } else {
                        // Other errors are at the server, so let's throw an error that will
                        // cause this sync to be retried at a later time
                        mService.errorLog("Throwing IOException; will retry later");
                        throw new IOException();
                    }
                }
            } else if (tag == EasTags.FOLDER_SYNC_KEY) {
                mAccount.mSyncKey = getValue();
                mService.userLog("New Account SyncKey: " + mAccount.mSyncKey);
            } else if (tag == EasTags.FOLDER_CHANGES) {
                changesParser();
            } else
                skipTag();
        }

        mAccount.saveOrUpdate(mContext);
        return res;
    }

    private Cursor getServerIdCursor(String serverId) {
        mBindArguments[0] = serverId;
        mBindArguments[1] = mAccountIdAsString;
        return mContentResolver.query(Mailbox.CONTENT_URI, new String[] {MailboxColumns.ID},
                WHERE_SERVER_ID_AND_ACCOUNT, mBindArguments, null);
    }

    public void deleteParser(ArrayList<ContentProviderOperation> ops) throws IOException {
        while (nextTag(EasTags.SYNC_DELETE) != END) {
            switch (tag) {
                case EasTags.FOLDER_SERVER_ID:
                    String serverId = getValue();
                    // Find the mailbox in this account with the given serverId
                    Cursor c = getServerIdCursor(serverId);
                    try {
                        if (c.moveToFirst()) {
                            mService.userLog("Deleting " + serverId);
                            ops.add(ContentProviderOperation.newDelete(
                                    ContentUris.withAppendedId(Mailbox.CONTENT_URI,
                                            c.getLong(0))).build());
                        }
                    } finally {
                        c.close();
                    }
                    break;
                default:
                    skipTag();
            }
        }
    }

    public void addParser(ArrayList<ContentProviderOperation> ops) throws IOException {
        String name = null;
        String serverId = null;
        String parentId = null;
        int type = 0;

        while (nextTag(EasTags.FOLDER_ADD) != END) {
            switch (tag) {
                case EasTags.FOLDER_DISPLAY_NAME: {
                    name = getValue();
                    break;
                }
                case EasTags.FOLDER_TYPE: {
                    type = getValueInt();
                    break;
                }
                case EasTags.FOLDER_PARENT_ID: {
                    parentId = getValue();
                    break;
                }
                case EasTags.FOLDER_SERVER_ID: {
                    serverId = getValue();
                    break;
                }
                default:
                    skipTag();
            }
        }
        if (mValidFolderTypes.contains(type)) {
            Mailbox m = new Mailbox();
            m.mDisplayName = name;
            m.mServerId = serverId;
            m.mAccountKey = mAccountId;
            m.mType = Mailbox.TYPE_MAIL;
            m.mSyncFrequency = Account.CHECK_INTERVAL_NEVER;
            switch (type) {
                case INBOX_TYPE:
                    m.mSyncFrequency = Account.CHECK_INTERVAL_PUSH;
                    m.mType = Mailbox.TYPE_INBOX;
                    break;
                case OUTBOX_TYPE:
                    m.mSyncFrequency = Account.CHECK_INTERVAL_NEVER;
                    // TYPE_OUTBOX mailboxes are known by SyncManager to sync whenever they aren't
                    // empty.  The value of mSyncFrequency is ignored for this kind of mailbox.
                    m.mType = Mailbox.TYPE_OUTBOX;
                    break;
                case SENT_TYPE:
                    m.mType = Mailbox.TYPE_SENT;
                    break;
                case DRAFTS_TYPE:
                    m.mType = Mailbox.TYPE_DRAFTS;
                    break;
                case DELETED_TYPE:
                    m.mType = Mailbox.TYPE_TRASH;
                    break;
                case CALENDAR_TYPE: 
                    m.mType = Mailbox.TYPE_CALENDAR;
                    // TODO This could be push, depending on settings
                    // For now, no sync, since it's not yet implemented
                    break;
                case CONTACTS_TYPE:
                    m.mType = Mailbox.TYPE_CONTACTS;
                    // TODO Frequency below should depend on settings
                    m.mSyncFrequency = Account.CHECK_INTERVAL_PUSH;
                    break;
            }

            // Make boxes like Contacts and Calendar invisible in the folder list
            m.mFlagVisible = (m.mType < Mailbox.TYPE_NOT_EMAIL);

            if (!parentId.equals("0")) {
                m.mParentServerId = parentId;
            }

            Log.v(TAG, "Adding mailbox: " + m.mDisplayName);
            ops.add(ContentProviderOperation
                    .newInsert(Mailbox.CONTENT_URI).withValues(m.toContentValues()).build());
        }

        return;
    }

    public void changesParser() throws IOException {
        // Keep track of new boxes, deleted boxes, updated boxes
        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

        while (nextTag(EasTags.FOLDER_CHANGES) != END) {
            // TODO Handle FOLDER_CHANGE and FOLDER_DELETE
            if (tag == EasTags.FOLDER_ADD) {
                addParser(ops);
            } else if (tag == EasTags.FOLDER_DELETE) {
                deleteParser(ops);
            } else if (tag == EasTags.FOLDER_COUNT) {
                getValueInt();
            } else
                skipTag();
        }

        // The mock stream is used for junit tests, so that the parsing code can be tested
        // separately from the provider code.
        // TODO Change tests to not require this; remove references to the mock stream
        if (mMock != null) {
            mMock.setResult(null);
            return;
        }

        // Create the new mailboxes in a single batch operation
        if (!ops.isEmpty()) {
            mService.userLog("Applying " + ops.size() + " mailbox operations.");

            // Then, we create an update for the account (most importantly, updating the syncKey)
            ops.add(ContentProviderOperation.newUpdate(
                    ContentUris.withAppendedId(Account.CONTENT_URI, mAccountId)).withValues(
                    mAccount.toContentValues()).build());

            // Finally, we execute the batch
            try {
                mService.mContext.getContentResolver()
                        .applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
                mService.userLog("New syncKey: " + mAccount.mSyncKey);
            } catch (RemoteException e) {
                // There is nothing to be done here; fail by returning null
            } catch (OperationApplicationException e) {
                // There is nothing to be done here; fail by returning null
            }

            // Look for sync issues and its children and delete them
            // I'm not aware of any other way to deal with this properly
            mBindArguments[0] = "Sync Issues";
            mBindArguments[1] = mAccountIdAsString;
            Cursor c = mContentResolver.query(Mailbox.CONTENT_URI, MAILBOX_ID_COLUMNS_PROJECTION,
                    WHERE_DISPLAY_NAME_AND_ACCOUNT, mBindArguments, null);
            String parentServerId = null;
            long id = 0;
            try {
                if (c.moveToFirst()) {
                    id = c.getLong(0);
                    parentServerId = c.getString(1);
                }
            } finally {
                c.close();
            }
            if (parentServerId != null) {
                mContentResolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, id),
                        null, null);
                mBindArguments[0] = parentServerId;
                mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_PARENT_SERVER_ID_AND_ACCOUNT,
                        mBindArguments);
            }
        }
    }

}
