/*
 * Copyright (C) 2012 Google Inc.
 * 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.mail.browse;

import com.google.common.annotations.VisibleForTesting;

import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.Layout.Alignment;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;
import android.text.format.DateUtils;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;

import com.android.mail.R;
import com.android.mail.browse.ConversationItemViewModel.SenderFragment;
import com.android.mail.perf.Timer;
import com.android.mail.providers.Address;
import com.android.mail.providers.Conversation;
import com.android.mail.providers.UIProvider.ConversationColumns;
import com.android.mail.ui.ConversationSelectionSet;
import com.android.mail.ui.ViewMode;
import com.android.mail.utils.Utils;

public class ConversationItemView extends View {
    // Timer.
    private static int sLayoutCount = 0;
    private static Timer sTimer; // Create the sTimer here if you need to do perf analysis.
    private static final int PERF_LAYOUT_ITERATIONS = 50;
    private static final String PERF_TAG_LAYOUT = "CCHV.layout";
    private static final String PERF_TAG_CALCULATE_TEXTS_BITMAPS = "CCHV.txtsbmps";
    private static final String PERF_TAG_CALCULATE_SENDER_SUBJECT = "CCHV.sendersubj";
    private static final String PERF_TAG_CALCULATE_LABELS = "CCHV.labels";
    private static final String PERF_TAG_CALCULATE_COORDINATES = "CCHV.coordinates";

    // Static bitmaps.
    private static Bitmap CHECKMARK_OFF;
    private static Bitmap CHECKMARK_ON;
    private static Bitmap STAR_OFF;
    private static Bitmap STAR_ON;
    private static Bitmap ATTACHMENT;
    private static Bitmap ONLY_TO_ME;
    private static Bitmap TO_ME_AND_OTHERS;
    private static Bitmap IMPORTANT_ONLY_TO_ME;
    private static Bitmap IMPORTANT_TO_ME_AND_OTHERS;
    private static Bitmap IMPORTANT_TO_OTHERS;
    private static Bitmap DATE_BACKGROUND;

    // Static colors.
    private static int DEFAULT_TEXT_COLOR;
    private static int ACTIVATED_TEXT_COLOR;
    private static int LIGHT_TEXT_COLOR;
    private static int DRAFT_TEXT_COLOR;
    private static int SUBJECT_TEXT_COLOR_READ;
    private static int SUBJECT_TEXT_COLOR_UNREAD;
    private static int SNIPPET_TEXT_COLOR_READ;
    private static int SNIPPET_TEXT_COLOR_UNREAD;
    private static int SENDERS_TEXT_COLOR_READ;
    private static int SENDERS_TEXT_COLOR_UNREAD;
    private static int DATE_TEXT_COLOR_READ;
    private static int DATE_TEXT_COLOR_UNREAD;
    private static int DATE_BACKGROUND_PADDING_LEFT;
    private static int TOUCH_SLOP;
    private static int sDateBackgroundHeight;
    private static int sStandardScaledDimen;
    private static CharacterStyle sLightTextStyle;
    private static CharacterStyle sNormalTextStyle;

    // Static paints.
    private static TextPaint sPaint = new TextPaint();
    private static TextPaint sLabelsPaint = new TextPaint();

    // Backgrounds for different states.
    private final SparseArray<Drawable> mBackgrounds = new SparseArray<Drawable>();

    // Dimensions and coordinates.
    private int mViewWidth = -1;
    private int mMode = -1;
    private int mDateX;
    private int mPaperclipX;
    private int mLabelsXEnd;
    private int mSendersWidth;

    /** Whether we're running under test mode. */
    private boolean mTesting = false;
    /** Whether we are on a tablet device or not */
    private final boolean mTabletDevice;

    @VisibleForTesting
    ConversationItemViewCoordinates mCoordinates;

    private final Context mContext;

    private String mAccount;
    private ConversationItemViewModel mHeader;
    private ViewMode mViewMode;
    private boolean mDownEvent;
    private boolean mChecked = false;
    private static int sFadedColor = -1;
    private static int sFadedActivatedColor = -1;
    private ConversationSelectionSet mSelectedConversationSet;

    static {
        sPaint.setAntiAlias(true);
        sLabelsPaint.setAntiAlias(true);
    }

    /**
     * This handler will be called when user toggle a star in a conversation
     * header view. It can be used to update the state of other views to ensure
     * UI consistency.
     */
    public static interface StarHandler {
        public void toggleStar(boolean toggleOn, long conversationId, long maxMessageId);
    }

    public ConversationItemView(Context context, String account) {
        super(context);
        mContext = context.getApplicationContext();
        mTabletDevice = Utils.useTabletUI(mContext);

        mAccount = account;
        Resources res = mContext.getResources();

        if (CHECKMARK_OFF == null) {
            // Initialize static bitmaps.
            CHECKMARK_OFF = BitmapFactory.decodeResource(res,
                    R.drawable.btn_check_off_normal_holo_light);
            CHECKMARK_ON = BitmapFactory.decodeResource(res,
                    R.drawable.btn_check_on_normal_holo_light);
            STAR_OFF = BitmapFactory.decodeResource(res,
                    R.drawable.btn_star_off_normal_email_holo_light);
            STAR_ON = BitmapFactory.decodeResource(res,
                    R.drawable.btn_star_on_normal_email_holo_light);
            ONLY_TO_ME = BitmapFactory.decodeResource(res, R.drawable.ic_email_caret_double);
            TO_ME_AND_OTHERS = BitmapFactory.decodeResource(res, R.drawable.ic_email_caret_single);
            IMPORTANT_ONLY_TO_ME = BitmapFactory.decodeResource(res,
                    R.drawable.ic_email_caret_double_important_unread);
            IMPORTANT_TO_ME_AND_OTHERS = BitmapFactory.decodeResource(res,
                    R.drawable.ic_email_caret_single_important_unread);
            IMPORTANT_TO_OTHERS = BitmapFactory.decodeResource(res,
                    R.drawable.ic_email_caret_none_important_unread);
            ATTACHMENT = BitmapFactory.decodeResource(res, R.drawable.ic_attachment_holo_light);
            DATE_BACKGROUND = BitmapFactory.decodeResource(res, R.drawable.folder_bg_holo_light);

            // Initialize colors.
            DEFAULT_TEXT_COLOR = res.getColor(R.color.default_text_color);
            ACTIVATED_TEXT_COLOR = res.getColor(android.R.color.white);
            LIGHT_TEXT_COLOR = res.getColor(R.color.light_text_color);
            DRAFT_TEXT_COLOR = res.getColor(R.color.drafts);
            SUBJECT_TEXT_COLOR_READ = res.getColor(R.color.subject_text_color_read);
            SUBJECT_TEXT_COLOR_UNREAD = res.getColor(R.color.subject_text_color_unread);
            SNIPPET_TEXT_COLOR_READ = res.getColor(R.color.snippet_text_color_read);
            SNIPPET_TEXT_COLOR_UNREAD = res.getColor(R.color.snippet_text_color_unread);
            SENDERS_TEXT_COLOR_READ = res.getColor(R.color.senders_text_color_read);
            SENDERS_TEXT_COLOR_UNREAD = res.getColor(R.color.senders_text_color_unread);
            DATE_TEXT_COLOR_READ = res.getColor(R.color.date_text_color_read);
            DATE_TEXT_COLOR_UNREAD = res.getColor(R.color.date_text_color_unread);
            DATE_BACKGROUND_PADDING_LEFT = res
                    .getDimensionPixelSize(R.dimen.date_background_padding_left);
            TOUCH_SLOP = res.getDimensionPixelSize(R.dimen.touch_slop);
            sDateBackgroundHeight = res.getDimensionPixelSize(R.dimen.date_background_height);
            sStandardScaledDimen = res.getDimensionPixelSize(R.dimen.standard_scaled_dimen);

            // Initialize static color.
            sNormalTextStyle = new StyleSpan(Typeface.NORMAL);
            sLightTextStyle = new ForegroundColorSpan(LIGHT_TEXT_COLOR);
        }
    }

    public void bind(Cursor cursor, StarHandler starHandler, String account,
            CharSequence displayedLabel, ViewMode viewMode, ConversationSelectionSet set) {
        mAccount = account;
        mViewMode = viewMode;
        mHeader = ConversationItemViewModel.forCursor(account, cursor);
        mSelectedConversationSet = set;
        setContentDescription(mHeader.getContentDescription(mContext));
        requestLayout();
    }

    public Conversation getConversation() {
        return mHeader.conversation;
    }

    /**
     * Sets the mode. Only used for testing.
     */
    @VisibleForTesting
    void setMode(int mode) {
        mMode = mode;
        mTesting = true;
    }

    private static void startTimer(String tag) {
        if (sTimer != null) {
            sTimer.start(tag);
        }
    }

    private static void pauseTimer(String tag) {
        if (sTimer != null) {
            sTimer.pause(tag);
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        startTimer(PERF_TAG_LAYOUT);

        super.onLayout(changed, left, top, right, bottom);

        int width = right - left;
        if (width != mViewWidth) {
            mViewWidth = width;
            if (!mTesting) {
                mMode = ConversationItemViewCoordinates.getMode(mContext, mViewMode);
            }
        }
        mHeader.viewWidth = mViewWidth;
        Resources res = getResources();
        mHeader.standardScaledDimen = res.getDimensionPixelOffset(R.dimen.standard_scaled_dimen);
        if (mHeader.standardScaledDimen != sStandardScaledDimen) {
            // Large Text has been toggle on/off. Update the static dimens.
            sStandardScaledDimen = mHeader.standardScaledDimen;
            ConversationItemViewCoordinates.refreshConversationHeights(mContext);
            sDateBackgroundHeight = res.getDimensionPixelSize(R.dimen.date_background_height);
        }
        mCoordinates = ConversationItemViewCoordinates.forWidth(mContext, mViewWidth, mMode,
                mHeader.standardScaledDimen);
        calculateTextsAndBitmaps();
        calculateCoordinates();
        mHeader.validate(mContext);

        pauseTimer(PERF_TAG_LAYOUT);
        if (sTimer != null && ++sLayoutCount >= PERF_LAYOUT_ITERATIONS) {
            sTimer.dumpResults();
            sTimer = new Timer();
            sLayoutCount = 0;
        }
    }

    @Override
    public void setBackgroundResource(int resourceId) {
        Drawable drawable = mBackgrounds.get(resourceId);
        if (drawable == null) {
            drawable = getResources().getDrawable(resourceId);
            mBackgrounds.put(resourceId, drawable);
        }
        if (getBackground() != drawable) {
            super.setBackgroundDrawable(drawable);
        }
    }

    private void calculateTextsAndBitmaps() {
        startTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS);
        if (mSelectedConversationSet != null) {
            mChecked = mSelectedConversationSet.contains(mHeader.conversation);
        }
        // Update font color.
        int fontColor = getFontColor(DEFAULT_TEXT_COLOR);
        boolean fontChanged = false;
        if (mHeader.fontColor != fontColor) {
            fontChanged = true;
            mHeader.fontColor = fontColor;
        }

        boolean isUnread = mHeader.unread;

        final boolean checkboxEnabled = true;
        if (mHeader.checkboxVisible != checkboxEnabled) {
            mHeader.checkboxVisible = checkboxEnabled;
        }

        // Update background.
        updateBackground(isUnread);

        if (mHeader.isLayoutValid(mContext)) {
            // Relayout subject if font color has changed.
            if (fontChanged) {
                createSubjectSpans(isUnread);
                layoutSubject();
            }
            pauseTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS);
            return;
        }

        // Initialize label displayer.
        startTimer(PERF_TAG_CALCULATE_LABELS);
        pauseTimer(PERF_TAG_CALCULATE_LABELS);

        // Star.
        mHeader.starBitmap = mHeader.starred ? STAR_ON : STAR_OFF;

        // Date.
        mHeader.dateText = DateUtils.getRelativeTimeSpanString(mContext,
                mHeader.conversation.dateMs).toString();

        // Paper clip icon.
        mHeader.paperclip = null;
        if (mHeader.conversation.hasAttachments) {
            mHeader.paperclip = ATTACHMENT;
        }

        // Personal level.
        mHeader.personalLevelBitmap = null;

        startTimer(PERF_TAG_CALCULATE_SENDER_SUBJECT);

        // Subject.
        createSubjectSpans(isUnread);

        // Parse senders fragments.
        parseSendersFragments(isUnread);

        pauseTimer(PERF_TAG_CALCULATE_SENDER_SUBJECT);
        pauseTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS);
    }

    private void createSubjectSpans(boolean isUnread) {
        final String subject = filterTag(mHeader.conversation.subject);
        final String snippet = mHeader.conversation.snippet;
        int subjectColor = isUnread ? SUBJECT_TEXT_COLOR_UNREAD : SUBJECT_TEXT_COLOR_READ;
        int snippetColor = isUnread ? SNIPPET_TEXT_COLOR_UNREAD : SNIPPET_TEXT_COLOR_READ;
        mHeader.subjectText = new SpannableStringBuilder(mContext.getString(
                R.string.subject_and_snippet, subject, snippet));
        if (isUnread) {
            mHeader.subjectText.setSpan(new StyleSpan(Typeface.BOLD), 0, subject.length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        int fontColor = getFontColor(subjectColor);
        mHeader.subjectText.setSpan(new ForegroundColorSpan(fontColor), 0,
                subject.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        fontColor = getFontColor(snippetColor);
        mHeader.subjectText.setSpan(new ForegroundColorSpan(fontColor), subject.length() + 1,
                mHeader.subjectText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

    private int getFontColor(int defaultColor) {
        return isActivated() && mTabletDevice ? ACTIVATED_TEXT_COLOR
                : defaultColor;
    }

    private void layoutSubject() {
        sPaint.setTextSize(mCoordinates.subjectFontSize);
        sPaint.setColor(mHeader.fontColor);
        mHeader.subjectLayout = new StaticLayout(mHeader.subjectText, sPaint,
                mCoordinates.subjectWidth, Alignment.ALIGN_NORMAL, 1, 0, true);
        if (mCoordinates.subjectLineCount < mHeader.subjectLayout.getLineCount()) {
            int end = mHeader.subjectLayout.getLineEnd(mCoordinates.subjectLineCount - 1);
            mHeader.subjectLayout = new StaticLayout(mHeader.subjectText.subSequence(0, end),
                    sPaint, mCoordinates.subjectWidth, Alignment.ALIGN_NORMAL, 1, 0, true);
        }
    }

    /**
     * Parses senders text into small fragments.
     */
    private void parseSendersFragments(boolean isUnread) {
        if (TextUtils.isEmpty(mHeader.conversation.senders)) {
            return;
        }
        mHeader.sendersText = formatSenders(mHeader.conversation.senders);
        mHeader.addSenderFragment(0, mHeader.sendersText.length(), sNormalTextStyle, true);
    }

    private String formatSenders(String sendersString) {
        String[] senders = TextUtils.split(sendersString, Address.ADDRESS_DELIMETER);
        String[] namesOnly = new String[senders.length];
        Rfc822Token[] senderTokens;
        String display;
        for (int i = 0; i < senders.length; i++) {
            senderTokens = Rfc822Tokenizer.tokenize(senders[i]);
            if (senderTokens != null && senderTokens.length > 0) {
                display = senderTokens[0].getName();
                if (TextUtils.isEmpty(display)) {
                    display = senderTokens[0].getAddress();
                }
                namesOnly[i] = display;
            }
        }
        return TextUtils.join(Address.ADDRESS_DELIMETER + " ", namesOnly);
    }

    private boolean canFitFragment(int width, int line, int fixedWidth) {
        if (line == mCoordinates.sendersLineCount) {
            return width + fixedWidth <= mSendersWidth;
        } else {
            return width <= mSendersWidth;
        }
    }

    private void calculateCoordinates() {
        startTimer(PERF_TAG_CALCULATE_COORDINATES);

        sPaint.setTextSize(mCoordinates.dateFontSize);
        sPaint.setTypeface(Typeface.DEFAULT);
        mDateX = mCoordinates.dateXEnd - (int) sPaint.measureText(mHeader.dateText);

        mPaperclipX = mDateX - ATTACHMENT.getWidth();

        int cellWidth = mContext.getResources().getDimensionPixelSize(R.dimen.label_cell_width);

        if (ConversationItemViewCoordinates.displayLabelsAboveDate(mMode)) {
            mLabelsXEnd = mCoordinates.dateXEnd;
            mSendersWidth = mCoordinates.sendersWidth;
        } else {
            if (mHeader.paperclip != null) {
                mLabelsXEnd = mPaperclipX;
            } else {
                mLabelsXEnd = mDateX - cellWidth / 2;
            }
            mSendersWidth = mLabelsXEnd - mCoordinates.sendersX - 2 * cellWidth;
        }

        if (mHeader.isLayoutValid(mContext)) {
            pauseTimer(PERF_TAG_CALCULATE_COORDINATES);
            return;
        }

        // Layout subject.
        layoutSubject();

        // First pass to calculate width of each fragment.
        int totalWidth = 0;
        int fixedWidth = 0;
        sPaint.setTextSize(mCoordinates.sendersFontSize);
        sPaint.setTypeface(Typeface.DEFAULT);
        for (SenderFragment senderFragment : mHeader.senderFragments) {
            CharacterStyle style = senderFragment.style;
            int start = senderFragment.start;
            int end = senderFragment.end;
            style.updateDrawState(sPaint);
            senderFragment.width = (int) sPaint.measureText(mHeader.sendersText, start, end);
            boolean isFixed = senderFragment.isFixed;
            if (isFixed) {
                fixedWidth += senderFragment.width;
            }
            totalWidth += senderFragment.width;
        }

        // Second pass to layout each fragment.
        int sendersY = mCoordinates.sendersY - mCoordinates.sendersAscent;
        if (!ConversationItemViewCoordinates.displaySendersInline(mMode)) {
            sendersY += totalWidth <= mSendersWidth ? mCoordinates.sendersLineHeight / 2 : 0;
        }
        totalWidth = 0;
        int currentLine = 1;
        boolean ellipsize = false;
        for (SenderFragment senderFragment : mHeader.senderFragments) {
            CharacterStyle style = senderFragment.style;
            int start = senderFragment.start;
            int end = senderFragment.end;
            int width = senderFragment.width;
            boolean isFixed = senderFragment.isFixed;
            style.updateDrawState(sPaint);

            // No more width available, we'll only show fixed fragments.
            if (ellipsize && !isFixed) {
                senderFragment.shouldDisplay = false;
                continue;
            }

            // New line and ellipsize text if needed.
            senderFragment.ellipsizedText = null;
            if (isFixed) {
                fixedWidth -= width;
            }
            if (!canFitFragment(totalWidth + width, currentLine, fixedWidth)) {
                // The text is too long, new line won't help. We have to
                // ellipsize text.
                if (totalWidth == 0) {
                    ellipsize = true;
                } else {
                    // New line.
                    if (currentLine < mCoordinates.sendersLineCount) {
                        currentLine++;
                        sendersY += mCoordinates.sendersLineHeight;
                        totalWidth = 0;
                        // The text is still too long, we have to ellipsize
                        // text.
                        if (totalWidth + width > mSendersWidth) {
                            ellipsize = true;
                        }
                    } else {
                        ellipsize = true;
                    }
                }

                if (ellipsize) {
                    width = mSendersWidth - totalWidth;
                    // No more new line, we have to reserve width for fixed
                    // fragments.
                    if (currentLine == mCoordinates.sendersLineCount) {
                        width -= fixedWidth;
                    }
                    senderFragment.ellipsizedText = TextUtils.ellipsize(
                            mHeader.sendersText.substring(start, end), sPaint, width,
                            TruncateAt.END).toString();
                    width = (int) sPaint.measureText(senderFragment.ellipsizedText);
                }
            }
            senderFragment.x = mCoordinates.sendersX + totalWidth;
            senderFragment.y = sendersY;
            senderFragment.shouldDisplay = true;
            totalWidth += width;
        }

        pauseTimer(PERF_TAG_CALCULATE_COORDINATES);
    }

    /**
     * If the subject contains the tag of a mailing-list (text surrounded with
     * []), return the subject with that tag ellipsized, e.g.
     * "[android-gmail-team] Hello" -> "[andr...] Hello"
     */
    private String filterTag(String subject) {
        String result = subject;
        String formatString = getContext().getResources().getString(R.string.filtered_tag);
        if (!TextUtils.isEmpty(subject) && subject.charAt(0) == '[') {
            int end = subject.indexOf(']');
            if (end > 0) {
                String tag = subject.substring(1, end);
                result = String.format(formatString, Utils.ellipsize(tag, 7),
                        subject.substring(end + 1));
            }
        }
        return result;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec,
                ConversationItemViewCoordinates.getMode(mContext, mViewMode));
        setMeasuredDimension(width, height);
    }

    /**
     * Determine the width of this view.
     *
     * @param measureSpec A measureSpec packed into an int
     * @return The width of the view, honoring constraints from measureSpec
     */
    private int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be
            result = specSize;
        } else {
            // Measure the text
            result = mViewWidth;
            if (specMode == MeasureSpec.AT_MOST) {
                // Respect AT_MOST value if that was what is called for by
                // measureSpec
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    /**
     * Determine the height of this view.
     *
     * @param measureSpec A measureSpec packed into an int
     * @param mode The current mode of this view
     * @return The height of the view, honoring constraints from measureSpec
     */
    private int measureHeight(int measureSpec, int mode) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be
            result = specSize;
        } else {
            // Measure the text
            result = ConversationItemViewCoordinates.getHeight(mContext, mode);
            if (specMode == MeasureSpec.AT_MOST) {
                // Respect AT_MOST value if that was what is called for by
                // measureSpec
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // Check mark.
        if (mHeader.checkboxVisible) {
            Bitmap checkmark = mChecked ? CHECKMARK_ON : CHECKMARK_OFF;
            canvas.drawBitmap(checkmark, mCoordinates.checkmarkX, mCoordinates.checkmarkY, sPaint);
        }

        // Personal Level.
        if (mHeader.personalLevelBitmap != null) {
            canvas.drawBitmap(mHeader.personalLevelBitmap, mCoordinates.personalLevelX,
                    mCoordinates.personalLevelY, sPaint);
        }

        // Senders.
        sPaint.setTextSize(mCoordinates.sendersFontSize);
        sPaint.setTypeface(Typeface.DEFAULT);
        boolean isUnread = mHeader.unread;
        int sendersColor = getFontColor(isUnread ? SENDERS_TEXT_COLOR_UNREAD
                : SENDERS_TEXT_COLOR_READ);
        sPaint.setColor(sendersColor);
        for (SenderFragment fragment : mHeader.senderFragments) {
            if (fragment.shouldDisplay) {
                sPaint.setTypeface(Typeface.DEFAULT);
                fragment.style.updateDrawState(sPaint);
                if (fragment.ellipsizedText != null) {
                    canvas.drawText(fragment.ellipsizedText, fragment.x, fragment.y, sPaint);
                } else {
                    canvas.drawText(mHeader.sendersText, fragment.start, fragment.end, fragment.x,
                            fragment.y, sPaint);
                }
            }
        }

        // Subject.
        sPaint.setTextSize(mCoordinates.subjectFontSize);
        sPaint.setTypeface(Typeface.DEFAULT);
        sPaint.setColor(mHeader.fontColor);
        canvas.save();
        canvas.translate(mCoordinates.subjectX,
                mCoordinates.subjectY + mHeader.subjectLayout.getTopPadding());
        mHeader.subjectLayout.draw(canvas);
        canvas.restore();

        // Date background: shown when there is an attachment or a visible
        // label.
        if (!isActivated()
                && mHeader.conversation.hasAttachments
                && ConversationItemViewCoordinates.showAttachmentBackground(mMode)) {
            mHeader.dateBackground = DATE_BACKGROUND;
            int leftOffset = (mHeader.conversation.hasAttachments ? mPaperclipX : mDateX)
                    - DATE_BACKGROUND_PADDING_LEFT;
            int top = mCoordinates.labelsY;
            Rect src = new Rect(0, 0, mHeader.dateBackground.getWidth(), mHeader.dateBackground
                    .getHeight());
            Rect dst = new Rect(leftOffset, top, mViewWidth, top + sDateBackgroundHeight);
            canvas.drawBitmap(mHeader.dateBackground, src, dst, sPaint);
        } else {
            mHeader.dateBackground = null;
        }

        // Date.
        sPaint.setTextSize(mCoordinates.dateFontSize);
        sPaint.setTypeface(Typeface.DEFAULT);
        sPaint.setColor(isUnread ? DATE_TEXT_COLOR_UNREAD : DATE_TEXT_COLOR_READ);
        drawText(canvas, mHeader.dateText, mDateX, mCoordinates.dateY - mCoordinates.dateAscent,
                sPaint);

        // Paper clip icon.
        if (mHeader.paperclip != null) {
            canvas.drawBitmap(mHeader.paperclip, mPaperclipX, mCoordinates.paperclipY, sPaint);
        }

        if (mHeader.faded) {
            int fadedColor = -1;
            if (sFadedActivatedColor == -1) {
                sFadedActivatedColor = mContext.getResources().getColor(
                        R.color.faded_activated_conversation_header);
            }
            fadedColor = sFadedActivatedColor;
            int restoreState = canvas.save();
            Rect bounds = canvas.getClipBounds();
            canvas.clipRect(bounds.left, bounds.top, bounds.right
                    - mContext.getResources().getDimensionPixelSize(R.dimen.triangle_width),
                    bounds.bottom);
            canvas.drawARGB(Color.alpha(fadedColor), Color.red(fadedColor),
                    Color.green(fadedColor), Color.blue(fadedColor));
            canvas.restoreToCount(restoreState);
        }

        // Star.
        canvas.drawBitmap(mHeader.starBitmap, mCoordinates.starX, mCoordinates.starY, sPaint);
    }

    private void drawText(Canvas canvas, CharSequence s, int x, int y, TextPaint paint) {
        canvas.drawText(s, 0, s.length(), x, y, paint);
    }

    private void updateBackground(boolean isUnread) {
        if (isUnread) {
            if (mTabletDevice && mViewMode.getMode() == ViewMode.CONVERSATION_LIST) {
                if (mChecked) {
                    setBackgroundResource(R.drawable.list_conversation_wide_unread_selected_holo);
                } else {
                    setBackgroundResource(R.drawable.conversation_wide_unread_selector);
                }
            } else {
                if (mChecked) {
                    setCheckedActivatedBackground();
                } else {
                    setBackgroundResource(R.drawable.conversation_unread_selector);
                }
            }
        } else {
            if (mTabletDevice && mViewMode.getMode() == ViewMode.CONVERSATION_LIST) {
                if (mChecked) {
                    setBackgroundResource(R.drawable.list_conversation_wide_read_selected_holo);
                } else {
                    setBackgroundResource(R.drawable.conversation_wide_read_selector);
                }
            } else {
                if (mChecked) {
                    setCheckedActivatedBackground();
                } else {
                    setBackgroundResource(R.drawable.conversation_read_selector);
                }
            }
        }
    }

    private void setCheckedActivatedBackground() {
        if (isActivated() && mTabletDevice) {
            setBackgroundResource(R.drawable.list_arrow_selected_holo);
        } else {
            setBackgroundResource(R.drawable.list_selected_holo);
        }
    }

    /**
     * Toggle the check mark on this view and update the conversation
     */
    public void toggleCheckMark() {
        mChecked = !mChecked;
        Conversation conv = mHeader.conversation;
        // Set the list position of this item in the conversation
        conv.position = mChecked ? ((ListView)getParent()).getPositionForView(this)
                : Conversation.NO_POSITION;
        if (mSelectedConversationSet != null) {
            mSelectedConversationSet.toggle(conv);
        }
        // We update the background after the checked state has changed now that
        // we have a selected background asset. Setting the background usually
        // waits for a layout pass, but we don't need a full layout, just an
        // update to the background.
        requestLayout();
    }

    /**
     * Toggle the star on this view and update the conversation.
     */
    private void toggleStar() {
        mHeader.starred = !mHeader.starred;
        mHeader.starBitmap = mHeader.starred ? STAR_ON : STAR_OFF;
        postInvalidate(mCoordinates.starX, mCoordinates.starY, mCoordinates.starX
                + mHeader.starBitmap.getWidth(),
                mCoordinates.starY + mHeader.starBitmap.getHeight());
        // Generalize this...
        mHeader.conversation.updateBoolean(mContext, ConversationColumns.STARRED, mHeader.starred);
    }

    private boolean touchCheckmark(float x, float y) {
        // Everything before senders and include a touch slop.
        return mHeader.checkboxVisible && x < mCoordinates.sendersX + TOUCH_SLOP;
    }

    private boolean touchStar(float x, float y) {
        // Everything after the star and include a touch slop.
        return x > mCoordinates.starX - TOUCH_SLOP;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean handled = false;

        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownEvent = true;
                if (touchCheckmark(x, y) || touchStar(x, y)) {
                    handled = true;
                }
                break;

            case MotionEvent.ACTION_CANCEL:
                mDownEvent = false;
                break;

            case MotionEvent.ACTION_UP:
                if (mDownEvent) {
                    if (touchCheckmark(x, y)) {
                        // Touch on the check mark
                        toggleCheckMark();
                    } else if (touchStar(x, y)) {
                        // Touch on the star
                        toggleStar();
                    }
                    handled = true;
                }
                break;
        }

        if (!handled) {
            handled = super.onTouchEvent(event);
        }

        return handled;
    }
}
