/*
 * 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.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.TimeZone;

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

import com.android.email.provider.EmailProvider;
import com.android.exchange.EasSyncService;
import com.android.exchange.EmailContent.Attachment;
import com.android.exchange.EmailContent.Mailbox;
import com.android.exchange.EmailContent.Message;
import com.android.exchange.EmailContent.MessageColumns;
import com.android.exchange.EmailContent.SyncColumns;

/**
 * Sync adapter for EAS email
 *
 */
public class EasEmailSyncAdapter extends EasSyncAdapter {

    private static final int UPDATES_READ_COLUMN = 0;
    private static final int UPDATES_MAILBOX_KEY_COLUMN = 1;
    private static final int UPDATES_SERVER_ID_COLUMN = 2;
    private static final String[] UPDATES_PROJECTION =
        {MessageColumns.FLAG_READ, MessageColumns.MAILBOX_KEY, SyncColumns.SERVER_ID};

    String[] bindArguments = new String[2];

    ArrayList<Long> mDeletedIdList = new ArrayList<Long>();

    ArrayList<Long> mUpdatedIdList = new ArrayList<Long>();

    public EasEmailSyncAdapter(Mailbox mailbox) {
        super(mailbox);
    }

    @Override
    public boolean parse(ByteArrayInputStream is, EasSyncService service) throws IOException {
        EasEmailSyncParser p = new EasEmailSyncParser(is, service);
        return p.parse();
    }

    class EasEmailSyncParser extends EasContentParser {

        private static final String WHERE_SERVER_ID_AND_MAILBOX_KEY = 
            SyncColumns.SERVER_ID + "=? and " + MessageColumns.MAILBOX_KEY + "=?";

        private String mMailboxIdAsString;

        public EasEmailSyncParser(InputStream in, EasSyncService service) throws IOException {
            super(in, service);
            mMailboxIdAsString = Long.toString(mMailbox.mId);
            //setDebug(true); // DON'T CHECK IN WITH THIS
        }

        public void wipe() {
            mContentResolver.delete(Message.CONTENT_URI,
                    Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
            mContentResolver.delete(Message.DELETED_CONTENT_URI,
                    Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
            mContentResolver.delete(Message.UPDATED_CONTENT_URI,
                    Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
        }

        public void addData (Message msg) throws IOException {
            String to = "";
            String from = "";
            String cc = "";
            String replyTo = "";
            int size = 0;

            ArrayList<Attachment> atts = new ArrayList<Attachment>();

            while (nextTag(EasTags.SYNC_APPLICATION_DATA) != END) {
                switch (tag) {
                    case EasTags.EMAIL_ATTACHMENTS:
                        break;
                    case EasTags.EMAIL_ATTACHMENT:
                        attachmentParser(atts, msg);
                        break;
                    case EasTags.EMAIL_TO:
                        to = getValue();
                        break;
                    case EasTags.EMAIL_FROM:
                        from = getValue();
                        String sender = from;
                        int q = from.indexOf('\"');
                        if (q >= 0) {
                            int qq = from.indexOf('\"', q + 1);
                            if (qq > 0) {
                                sender = from.substring(q + 1, qq);
                            }
                        }
                        msg.mDisplayName = sender;
                        break;
                    case EasTags.EMAIL_CC:
                        cc = getValue();
                        break;
                    case EasTags.EMAIL_REPLY_TO:
                        replyTo = getValue();
                        break;
                    case EasTags.EMAIL_DATE_RECEIVED:
                        String date = getValue();
                        // 2009-02-11T18:03:03.627Z
                        GregorianCalendar cal = new GregorianCalendar();
                        cal.set(Integer.parseInt(date.substring(0, 4)), Integer.parseInt(date
                                .substring(5, 7)) - 1, Integer.parseInt(date.substring(8, 10)),
                                Integer.parseInt(date.substring(11, 13)), Integer.parseInt(date
                                        .substring(14, 16)), Integer.parseInt(date
                                                .substring(17, 19)));
                        cal.setTimeZone(TimeZone.getTimeZone("GMT"));
                        msg.mTimeStamp = cal.getTimeInMillis();
                        break;
                    case EasTags.EMAIL_SUBJECT:
                        msg.mSubject = getValue();
                        break;
                    case EasTags.EMAIL_READ:
                        msg.mFlagRead = getValueInt() == 1;
                        break;
                    case EasTags.EMAIL_BODY:
                        msg.mTextInfo = "X;X;8;" + size; // location;encoding;charset;size
                        msg.mText = getValue();
                        // For now...
                        msg.mPreview = "Fake preview"; // Messages.previewFromText(body);
                        break;
                    default:
                        skipTag();
                }
            }

            msg.mTo = to;
            msg.mFrom = from;
            msg.mCc = cc;
            msg.mReplyTo = replyTo;
            if (atts.size() > 0) {
                msg.mAttachments = atts;
            }

        }
        
        public void addParser(ArrayList<Message> emails) throws IOException {
            Message msg = new Message();
            msg.mAccountKey = mAccount.mId;
            msg.mMailboxKey = mMailbox.mId;
            msg.mFlagLoaded = Message.LOADED;

            while (nextTag(EasTags.SYNC_ADD) != END) {
                switch (tag) {
                    case EasTags.SYNC_SERVER_ID: 
                        msg.mServerId = getValue();
                        break;
                    case EasTags.SYNC_APPLICATION_DATA:
                        addData(msg);
                        break;
                    default:
                        skipTag();
                }
            }

            // Tell the provider that this is synced back
            msg.mServerVersion = mMailbox.mSyncKey;
            emails.add(msg);
        }

        public void attachmentParser(ArrayList<Attachment> atts, Message msg) throws IOException {
            String fileName = null;
            String length = null;
            String lvl = null;

            while (nextTag(EasTags.EMAIL_ATTACHMENT) != END) {
                switch (tag) {
                    case EasTags.EMAIL_DISPLAY_NAME:
                        fileName = getValue();
                        break;
                    case EasTags.EMAIL_ATT_NAME:
                        lvl = getValue();
                        break;
                    case EasTags.EMAIL_ATT_SIZE:
                        length = getValue();
                        break;
                    default:
                        skipTag();
                }
            }

            if (fileName != null && length != null && lvl != null) {
                Attachment att = new Attachment();
                att.mEncoding = "base64";
                att.mSize = Long.parseLong(length);
                att.mFileName = fileName;
                atts.add(att);
                msg.mFlagAttachment = true;
            }
        }

        private Cursor getServerIdCursor(String serverId, String[] projection) {
            bindArguments[0] = serverId;
            bindArguments[1] = mMailboxIdAsString;
            return mContentResolver.query(Message.CONTENT_URI, projection,
                    WHERE_SERVER_ID_AND_MAILBOX_KEY, bindArguments, null);
        }

        public void deleteParser(ArrayList<Long> deletes) throws IOException {
            while (nextTag(EasTags.SYNC_DELETE) != END) {
                switch (tag) {
                    case EasTags.SYNC_SERVER_ID:
                        String serverId = getValue();
                        // Find the message in this mailbox with the given serverId
                        Cursor c = getServerIdCursor(serverId, Message.ID_COLUMN_PROJECTION);
                        try {
                            if (c.moveToFirst()) {
                                mService.userLog("Deleting " + serverId);
                                deletes.add(c.getLong(Message.ID_COLUMNS_ID_COLUMN));
                            }
                        } finally {
                            c.close();
                        }
                        break;
                    default:
                        skipTag();
                }
            }
        }

        class ServerChange {
            long id;
            boolean read;

            ServerChange(long _id, boolean _read) {
                id = _id;
                read = _read;
            }
        }

        public void changeParser(ArrayList<ServerChange> changes) throws IOException {
            String serverId = null;
            boolean oldRead = false;
            boolean read = true;
            long id = 0;
            while (nextTag(EasTags.SYNC_CHANGE) != END) {
                switch (tag) {
                    case EasTags.SYNC_SERVER_ID:
                        serverId = getValue();
                        Cursor c = getServerIdCursor(serverId, Message.LIST_PROJECTION);
                        try {
                            if (c.moveToFirst()) {
                                mService.userLog("Changing " + serverId);
                                oldRead = c.getInt(Message.LIST_READ_COLUMN) == Message.READ;
                                id = c.getLong(Message.LIST_ID_COLUMN);
                            }
                        } finally {
                            c.close();
                        }
                        break;
                    case EasTags.EMAIL_READ:
                        read = getValueInt() == 1;
                        break;
                    case EasTags.SYNC_APPLICATION_DATA:
                        break;
                    default:
                        skipTag();
                }
            }
            if (oldRead != read) {
                changes.add(new ServerChange(id, read));
            }
        }

        public void commandsParser() throws IOException {
            ArrayList<Message> newEmails = new ArrayList<Message>();
            ArrayList<Long> deletedEmails = new ArrayList<Long>();
            ArrayList<ServerChange> changedEmails = new ArrayList<ServerChange>();

            while (nextTag(EasTags.SYNC_COMMANDS) != END) {
                if (tag == EasTags.SYNC_ADD) {
                    addParser(newEmails);
                } else if (tag == EasTags.SYNC_DELETE) {
                    deleteParser(deletedEmails);
                } else if (tag == EasTags.SYNC_CHANGE) {
                    changeParser(changedEmails);
                } else
                    skipTag();
            }

            // Use a batch operation to handle the changes
            // TODO New mail notifications?  Who looks for these?
            ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
            for (Message content : newEmails) {
                content.addSaveOps(ops);
            }
            for (Long id : deletedEmails) {
                ops.add(ContentProviderOperation.newDelete(
                        ContentUris.withAppendedId(Message.CONTENT_URI, id)).build());
            }
            if (!changedEmails.isEmpty()) {
                // Server wins in a conflict...
                for (ServerChange change : changedEmails) {
                    // For now, don't handle read->unread
                    ContentValues cv = new ContentValues();
                    cv.put(MessageColumns.FLAG_READ, change.read);
                    ops.add(ContentProviderOperation.newUpdate(
                            ContentUris.withAppendedId(Message.CONTENT_URI, change.id))
                                .withValues(cv)
                                .build());
                }
            }
            ops.add(ContentProviderOperation.newUpdate(
                    ContentUris.withAppendedId(Mailbox.CONTENT_URI, mMailbox.mId)).withValues(
                    mMailbox.toContentValues()).build());

            addCleanupOps(ops);
            
            try {
                mService.mContext.getContentResolver()
                        .applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
            } 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
            }

            mService.userLog("SyncKey confirmed as: " + mMailbox.mSyncKey);
        }

    }

    @Override
    public String getCollectionName() {
        return "Email";
    }

    private void addCleanupOps(ArrayList<ContentProviderOperation> ops) {
        // If we've sent local deletions, clear out the deleted table
        for (Long id: mDeletedIdList) {
            ops.add(ContentProviderOperation.newDelete(
                    ContentUris.withAppendedId(Message.DELETED_CONTENT_URI, id)).build());
        }
        // And same with the updates
        for (Long id: mUpdatedIdList) {
            ops.add(ContentProviderOperation.newDelete(
                    ContentUris.withAppendedId(Message.UPDATED_CONTENT_URI, id)).build());
        }
    }

    @Override
    public void cleanup(EasSyncService service) {
        if (!mDeletedIdList.isEmpty() || !mUpdatedIdList.isEmpty()) {
            ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
            addCleanupOps(ops);
            try {
                service.mContext.getContentResolver()
                    .applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
            } 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
            }
        }
    }

    @Override
    public boolean sendLocalChanges(EasSerializer s, EasSyncService service) throws IOException {
        Context context = service.mContext;
        ContentResolver cr = context.getContentResolver();

        // Find any of our deleted items
        Cursor c = cr.query(Message.DELETED_CONTENT_URI, Message.LIST_PROJECTION,
                MessageColumns.MAILBOX_KEY + '=' + mMailbox.mId, null, null);
        boolean first = true;
        // We keep track of the list of deleted item id's so that we can remove them from the
        // deleted table after the server receives our command
        mDeletedIdList.clear();
        try {
            while (c.moveToNext()) {
                if (first) {
                    s.start("Commands");
                    first = false;
                }
                // Send the command to delete this message
                s.start("Delete")
                    .data("ServerId", c.getString(Message.LIST_SERVER_ID_COLUMN))
                    .end("Delete");
                mDeletedIdList.add(c.getLong(Message.LIST_ID_COLUMN));
            }
        } finally {
            c.close();
        }

        // Find our trash mailbox, since deletions will have been moved there...
        long trashMailboxId =
            Mailbox.findMailboxOfType(context, mMailbox.mAccountKey, Mailbox.TYPE_TRASH);

        // Do the same now for updated items
        c = cr.query(Message.UPDATED_CONTENT_URI, Message.LIST_PROJECTION,
                MessageColumns.MAILBOX_KEY + '=' + mMailbox.mId, null, null);

        // We keep track of the list of updated item id's as we did above with deleted items
        mUpdatedIdList.clear();
        try {
            while (c.moveToNext()) {
                long id = c.getLong(Message.LIST_ID_COLUMN);
                // Say we've handled this update
                mUpdatedIdList.add(id);
                // We have the id of the changed item.  But first, we have to find out its current
                // state, since the updated table saves the opriginal state
                Cursor currentCursor = cr.query(ContentUris.withAppendedId(Message.CONTENT_URI, id),
                        UPDATES_PROJECTION, null, null, null);
                try {
                    // If this item no longer exists (shouldn't be possible), just move along
                    if (!currentCursor.moveToFirst()) {
                         continue;
                    }

                    // If the message is now in the trash folder, it has been deleted by the user
                    if (currentCursor.getLong(UPDATES_MAILBOX_KEY_COLUMN) == trashMailboxId) {
                         if (first) {
                            s.start("Commands");
                            first = false;
                        }
                        // Send the command to delete this message
                        s.start("Delete")
                            .data("ServerId", currentCursor.getString(UPDATES_SERVER_ID_COLUMN))
                            .end("Delete");
                        continue;
                    }

                    int read = currentCursor.getInt(UPDATES_READ_COLUMN);
                    if (read == c.getInt(Message.LIST_READ_COLUMN)) {
                        // The read state hasn't really changed, so move on...
                        continue;
                    }
                    if (first) {
                        s.start("Commands");
                        first = false;
                    }
                    // Send the change to "read".  We'll do "flagged" here eventually as well
                    // TODO Add support for flags here (EAS 12.0 and above)
                    s.start("Change")
                        .data("ServerId", c.getString(Message.LIST_SERVER_ID_COLUMN))
                        .start("ApplicationData")
                        .data("Read", Integer.toString(read))
                        .end("ApplicationData")
                        .end("Change");
                } finally {
                    currentCursor.close();
                }
            }
        } finally {
            c.close();
        }

        if (!first) {
            s.end("Commands");
        }
        return false;
    }
}
