/*
 * 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 com.android.email.Utility;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailProvider;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.AccountColumns;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.exchange.Eas;
import com.android.exchange.ExchangeService;
import com.android.exchange.MockParserStream;

import android.content.ContentProviderOperation;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.os.RemoteException;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

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

public class FolderSyncParser extends AbstractSyncParser {

    public static final String TAG = "FolderSyncParser";

    // These are defined by the EAS protocol
    public static final int USER_GENERIC_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;

    // Chunk size for our mailbox commits
    public final static int MAILBOX_COMMIT_SIZE = 20;

    // EAS types that we are willing to consider valid folders for EAS sync
    public static final List<Integer> VALID_EAS_FOLDER_TYPES = Arrays.asList(INBOX_TYPE,
            DRAFTS_TYPE, DELETED_TYPE, SENT_TYPE, OUTBOX_TYPE, USER_MAILBOX_TYPE, CALENDAR_TYPE,
            CONTACTS_TYPE, USER_GENERIC_TYPE);

    public static final String ALL_BUT_ACCOUNT_MAILBOX = MailboxColumns.ACCOUNT_KEY + "=? and " +
        MailboxColumns.TYPE + "!=" + Mailbox.TYPE_EAS_ACCOUNT_MAILBOX;

    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 long mAccountId;
    private String mAccountIdAsString;
    private MockParserStream mMock = null;
    private String[] mBindArguments = new String[2];
    private ArrayList<ContentProviderOperation> mOperations =
        new ArrayList<ContentProviderOperation>();

    public FolderSyncParser(InputStream in, AbstractSyncAdapter adapter) throws IOException {
        super(in, adapter);
        mAccountId = mAccount.mId;
        mAccountIdAsString = Long.toString(mAccountId);
        if (in instanceof MockParserStream) {
            mMock = (MockParserStream)in;
        }
    }

    @Override
    public boolean parse() throws IOException {
        int status;
        boolean res = false;
        boolean resetFolders = false;
        // Since we're now (potentially) committing mailboxes in chunks, ensure that we start with
        // only the account mailbox
        String key = mAccount.mSyncKey;
        boolean initialSync = (key == null) || "0".equals(key);
        if (initialSync) {
            mContentResolver.delete(Mailbox.CONTENT_URI, ALL_BUT_ACCOUNT_MAILBOX,
                    new String[] {Long.toString(mAccountId)});
        }
        if (nextTag(START_DOCUMENT) != Tags.FOLDER_FOLDER_SYNC)
            throw new EasParserException();
        while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
            if (tag == Tags.FOLDER_STATUS) {
                status = getValueInt();
                if (status != Eas.FOLDER_STATUS_OK) {
                    mService.errorLog("FolderSync failed: " + status);
                    if (status == Eas.FOLDER_STATUS_INVALID_KEY) {
                        mService.errorLog("Bad sync key; RESET and delete all folders");
                        // Reset the sync key and save
                        mAccount.mSyncKey = "0";
                        ContentValues cv = new ContentValues();
                        cv.put(AccountColumns.SYNC_KEY, mAccount.mSyncKey);
                        mContentResolver.update(ContentUris.withAppendedId(Account.CONTENT_URI,
                                mAccount.mId), cv, null, null);
                        // Delete PIM data
                        ExchangeService.deleteAccountPIMData(mAccountId);
                        // And only then, delete mailboxes
                        mContentResolver.delete(Mailbox.CONTENT_URI, ALL_BUT_ACCOUNT_MAILBOX,
                                new String[] {Long.toString(mAccountId)});
                        // Stop existing syncs and reconstruct _main
                        ExchangeService.stopNonAccountMailboxSyncsForAccount(mAccountId);
                        res = true;
                        resetFolders = 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 EasParserException("Folder status error");
                    }
                }
            } else if (tag == Tags.FOLDER_SYNC_KEY) {
                mAccount.mSyncKey = getValue();
                userLog("New Account SyncKey: ", mAccount.mSyncKey);
            } else if (tag == Tags.FOLDER_CHANGES) {
                changesParser(mOperations, initialSync);
            } else
                skipTag();
        }
        synchronized (mService.getSynchronizer()) {
            if (!mService.isStopped() || resetFolders) {
                commit();
                userLog("Leaving FolderSyncParser with Account syncKey=", mAccount.mSyncKey);
            }
        }
        return res;
    }

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

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

    public Mailbox addParser() throws IOException {
        String name = null;
        String serverId = null;
        String parentId = null;
        int type = 0;

        while (nextTag(Tags.FOLDER_ADD) != END) {
            switch (tag) {
                case Tags.FOLDER_DISPLAY_NAME: {
                    name = getValue();
                    break;
                }
                case Tags.FOLDER_TYPE: {
                    type = getValueInt();
                    break;
                }
                case Tags.FOLDER_PARENT_ID: {
                    parentId = getValue();
                    break;
                }
                case Tags.FOLDER_SERVER_ID: {
                    serverId = getValue();
                    break;
                }
                default:
                    skipTag();
            }
        }

        if (VALID_EAS_FOLDER_TYPES.contains(type)) {
            Mailbox mailbox = new Mailbox();
            mailbox.mDisplayName = name;
            mailbox.mServerId = serverId;
            mailbox.mAccountKey = mAccountId;
            mailbox.mType = Mailbox.TYPE_MAIL;
            // Note that all mailboxes default to checking "never" (i.e. manual sync only)
            // We set specific intervals for inbox, contacts, and (eventually) calendar
            mailbox.mSyncInterval = Mailbox.CHECK_INTERVAL_NEVER;
            switch (type) {
                case INBOX_TYPE:
                    mailbox.mType = Mailbox.TYPE_INBOX;
                    mailbox.mSyncInterval = mAccount.mSyncInterval;
                    break;
                case CONTACTS_TYPE:
                    mailbox.mType = Mailbox.TYPE_CONTACTS;
                    mailbox.mSyncInterval = mAccount.mSyncInterval;
                    break;
                case OUTBOX_TYPE:
                    // TYPE_OUTBOX mailboxes are known by ExchangeService to sync whenever they
                    // aren't empty.  The value of mSyncFrequency is ignored for this kind of
                    // mailbox.
                    mailbox.mType = Mailbox.TYPE_OUTBOX;
                    break;
                case SENT_TYPE:
                    mailbox.mType = Mailbox.TYPE_SENT;
                    break;
                case DRAFTS_TYPE:
                    mailbox.mType = Mailbox.TYPE_DRAFTS;
                    break;
                case DELETED_TYPE:
                    mailbox.mType = Mailbox.TYPE_TRASH;
                    break;
                case CALENDAR_TYPE:
                    mailbox.mType = Mailbox.TYPE_CALENDAR;
                    mailbox.mSyncInterval = mAccount.mSyncInterval;
                    break;
                case USER_GENERIC_TYPE:
                    mailbox.mType = Mailbox.TYPE_UNKNOWN;
                    break;
            }

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

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

            return mailbox;
        }
        return null;
    }

    /**
     * Determine whether a given mailbox holds mail, rather than other data.  We do this by first
     * checking the type of the mailbox (if it's a known good type, great; if it's a known bad
     * type, return false).  If it's unknown, we check the parent, first by trying to find it in
     * the current set of newly synced items, and then by looking it up in EmailProvider.  If
     * we can find the parent, we use the same rules to determine if it holds mail; if it does,
     * then its children do as well, so that's a go.
     *
     * @param mailbox the mailbox we're checking
     * @param mailboxMap a HashMap relating server id's of mailboxes in the current sync set to
     * the corresponding mailbox structures
     * @return whether or not the mailbox contains email (rather than PIM or unknown data)
     */
    /*package*/ boolean isValidMailFolder(Mailbox mailbox, HashMap<String, Mailbox> mailboxMap) {
        int folderType = mailbox.mType;
        // Automatically accept our email types
        if (folderType < Mailbox.TYPE_NOT_EMAIL) return true;
        // Automatically reject everything else but "unknown"
        if (folderType != Mailbox.TYPE_UNKNOWN) return false;
        // If this is TYPE_UNKNOWN, check the parent
        Mailbox parent = mailboxMap.get(mailbox.mParentServerId);
        // If the parent is in the map, then check it out; if not, it could be an existing saved
        // Mailbox, so we'll have to query the database
        if (parent == null) {
            mBindArguments[0] = Long.toString(mAccount.mId);
            mBindArguments[1] = mailbox.mParentServerId;
            long parentId = Utility.getFirstRowInt(mContext, Mailbox.CONTENT_URI,
                    EmailContent.ID_PROJECTION,
                    MailboxColumns.ACCOUNT_KEY + "=? AND " + MailboxColumns.SERVER_ID + "=?",
                    mBindArguments, null, EmailContent.ID_PROJECTION_COLUMN, -1);
            if (parentId != -1) {
                // Get the parent from the database
                parent = Mailbox.restoreMailboxWithId(mContext, parentId);
                if (parent == null) return false;
            } else {
                return false;
            }
        }
        return isValidMailFolder(parent, mailboxMap);
    }

    public void updateParser(ArrayList<ContentProviderOperation> ops) throws IOException {
        String serverId = null;
        String displayName = null;
        String parentId = null;
        while (nextTag(Tags.FOLDER_UPDATE) != END) {
            switch (tag) {
                case Tags.FOLDER_SERVER_ID:
                    serverId = getValue();
                    break;
                case Tags.FOLDER_DISPLAY_NAME:
                    displayName = getValue();
                    break;
                case Tags.FOLDER_PARENT_ID:
                    parentId = getValue();
                    break;
                default:
                    skipTag();
                    break;
            }
        }
        // We'll make a change if one of parentId or displayName are specified
        // serverId is required, but let's be careful just the same
        if (serverId != null && (displayName != null || parentId != null)) {
            Cursor c = getServerIdCursor(serverId);
            try {
                // If we find the mailbox (using serverId), make the change
                if (c.moveToFirst()) {
                    userLog("Updating ", serverId);
                    ContentValues cv = new ContentValues();
                    if (displayName != null) {
                        cv.put(Mailbox.DISPLAY_NAME, displayName);
                    }
                    if (parentId != null) {
                        cv.put(Mailbox.PARENT_SERVER_ID, parentId);
                    }
                    ops.add(ContentProviderOperation.newUpdate(
                            ContentUris.withAppendedId(Mailbox.CONTENT_URI,
                                    c.getLong(0))).withValues(cv).build());
                }
            } finally {
                c.close();
            }
        }
    }

    private boolean commitMailboxes(ArrayList<Mailbox> validMailboxes,
            ArrayList<Mailbox> userMailboxes, HashMap<String, Mailbox> mailboxMap,
            ArrayList<ContentProviderOperation> ops) {

        // Go through the generic user mailboxes; we'll call them valid if any parent is valid
        for (Mailbox m: userMailboxes) {
            if (isValidMailFolder(m, mailboxMap)) {
                m.mType = Mailbox.TYPE_MAIL;
                validMailboxes.add(m);
            } else {
                userLog("Rejecting unknown type mailbox: " + m.mDisplayName);
            }
        }

        // Add operations for all valid mailboxes
        for (Mailbox m: validMailboxes) {
            userLog("Adding mailbox: ", m.mDisplayName);
            ops.add(ContentProviderOperation
                    .newInsert(Mailbox.CONTENT_URI).withValues(m.toContentValues()).build());
        }

        // Commit the mailboxes
        userLog("Applying ", mOperations.size(), " mailbox operations.");
        // Execute the batch; throw IOExceptions if this fails, hoping the issue isn't repeatable
        // If it IS repeatable, there's no good result, since the folder list will be invalid
        try {
            mContentResolver.applyBatch(EmailProvider.EMAIL_AUTHORITY, mOperations);
            return true;
        } catch (RemoteException e) {
            userLog("RemoteException in commitMailboxes");
            return false;
        } catch (OperationApplicationException e) {
            userLog("OperationApplicationException in commitMailboxes");
            return false;
        }
    }

    public void changesParser(final ArrayList<ContentProviderOperation> ops,
            final boolean initialSync) throws IOException {
        // Array of added mailboxes
        final ArrayList<Mailbox> addMailboxes = new ArrayList<Mailbox>();

        while (nextTag(Tags.FOLDER_CHANGES) != END) {
            if (tag == Tags.FOLDER_ADD) {
                Mailbox mailbox = addParser();
                if (mailbox != null) {
                    addMailboxes.add(mailbox);
                }
            } else if (tag == Tags.FOLDER_DELETE) {
                deleteParser(ops);
            } else if (tag == Tags.FOLDER_UPDATE) {
                updateParser(ops);
            } else if (tag == Tags.FOLDER_COUNT) {
                getValueInt();
            } else
                skipTag();
        }

        Utility.runAsync(new Runnable() {
            @Override
            public void run() {
                // Synchronize on the parser to prevent this being run multiple times concurrently
                // (an extremely unlikely event, but nonetheless possible)
                synchronized (FolderSyncParser.this) {
                    // Mailboxes that we known contain email
                    ArrayList<Mailbox> validMailboxes = new ArrayList<Mailbox>();
                    // Mailboxes that we're unsure about
                    ArrayList<Mailbox> userMailboxes = new ArrayList<Mailbox>();
                    // Maps folder serverId to mailbox type
                    HashMap<String, Mailbox> mailboxMap = new HashMap<String, Mailbox>();
                    int mailboxCommitCount = 0;
                    for (Mailbox mailbox : addMailboxes) {
                        // Save away the type of this folder
                        mailboxMap.put(mailbox.mServerId, mailbox);
                        // And add the mailbox to the proper list
                        if (type == USER_MAILBOX_TYPE) {
                            userMailboxes.add(mailbox);
                        } else {
                            validMailboxes.add(mailbox);
                        }
                        // On initial sync, we commit what we have every 20 mailboxes
                        if (initialSync && (++mailboxCommitCount == MAILBOX_COMMIT_SIZE)) {
                            if (!commitMailboxes(validMailboxes, userMailboxes, mailboxMap, ops)) {
                                mService.stop();
                                return;
                            }
                            // Clear our arrays to prepare for more
                            userMailboxes.clear();
                            validMailboxes.clear();
                            ops.clear();
                            mailboxCommitCount = 0;
                        }
                    }
                    // Commit the sync key and mailboxes
                    ContentValues cv = new ContentValues();
                    cv.put(AccountColumns.SYNC_KEY, mAccount.mSyncKey);
                    ops.add(ContentProviderOperation
                            .newUpdate(
                                    ContentUris.withAppendedId(Account.CONTENT_URI, mAccount.mId))
                            .withValues(cv).build());
                    if (!commitMailboxes(validMailboxes, userMailboxes, mailboxMap, ops)) {
                        mService.stop();
                    }
                }
            }});
    }

    /**
     * Not needed for FolderSync parsing; everything is done within changesParser
     */
    @Override
    public void commandsParser() throws IOException {
    }

    /**
     * Clean up after sync
     */
    @Override
    public void commit() throws IOException {
        // 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);
        }
    }

    @Override
    public void responsesParser() throws IOException {
    }

}
