package foundation.e.mail.fragment;


import android.content.Context;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.format.DateUtils;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.Locale;

import foundation.e.mail.Account;
import foundation.e.mail.K9;
import foundation.e.mail.R;
import foundation.e.mail.RoundedQuickContactBadge;
import foundation.e.mail.helper.Utility;
import foundation.e.mail.mail.Address;
import foundation.e.mail.mailstore.DatabasePreviewType;
import foundation.e.mail.ui.ContactBadge;

import static foundation.e.mail.fragment.MLFProjectionInfo.ANSWERED_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.ATTACHMENT_COUNT_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.CC_LIST_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.DATE_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.FLAGGED_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.FOLDER_NAME_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.FORWARDED_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.PREVIEW_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.PREVIEW_TYPE_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.READ_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.SENDER_LIST_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.SUBJECT_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.THREAD_COUNT_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.TO_LIST_COLUMN;
import static foundation.e.mail.fragment.MLFProjectionInfo.UID_COLUMN;


public class MessageListAdapter extends CursorAdapter {

    private final MessageListFragment fragment;
    private Drawable mForwardedIcon;
    private Drawable mAnsweredIcon;
    private Drawable mForwardedAnsweredIcon;

    MessageListAdapter(MessageListFragment fragment) {
        super(fragment.getActivity(), null, 0);
        this.fragment = fragment;
        mAnsweredIcon = fragment.getResources().getDrawable(R.drawable.ic_reply_light);
        mForwardedIcon = fragment.getResources().getDrawable(R.drawable.ic_forward_light);
        mForwardedAnsweredIcon = fragment.getResources().getDrawable(R.drawable.ic_reply_light);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        // Inflate the message lst item
	View view = fragment.getK9LayoutInflater().inflate(R.layout.message_list_item, parent, false);

        MessageViewHolder holder = new MessageViewHolder(fragment);
        
	holder.date = (TextView) view.findViewById(R.id.date);

        if (fragment.previewLines == 0 && fragment.contactsPictureLoader == null) {
            view.findViewById(R.id.preview_text_view).setVisibility(View.GONE);
        } else {
            holder.preview = (TextView) view.findViewById(R.id.preview_text_view);
        }

        RoundedQuickContactBadge contactBadge =
                (RoundedQuickContactBadge) view.findViewById(R.id.contact_badge);

	// Assign a reference to Star ImageView 
        holder.starImageView = (ImageView) view.findViewById(R.id.star_image_view);

	// Assign a reference to Reply Status ImageView
        holder.replyStatusImageView = (ImageView) view.findViewById(R.id.reply_status_image_view);

        // Assign a reference to Attachment ImageView
        holder.attachmentImageView = (ImageView) view.findViewById(R.id.attachment_image_view);

        if (fragment.contactsPictureLoader != null) {
            holder.contactBadge = contactBadge;
        } else {
            contactBadge.setVisibility(View.GONE);
        }

	holder.from = (TextView) view.findViewById(R.id.from_text_view);

	holder.subject = (TextView) view.findViewById(R.id.subject_text_view);

        holder.threadCount = (TextView) view.findViewById(R.id.thread_count);
        view.findViewById(R.id.selected_checkbox_wrapper).setVisibility((fragment.checkboxes) ? View.VISIBLE : View.GONE);

        holder.selected = (CheckBox) view.findViewById(R.id.selected_checkbox);
        holder.selected.setOnClickListener(holder);


        view.setTag(holder);

        return view;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        Account account = fragment.getAccountFromCursor(cursor);

        String fromList = cursor.getString(SENDER_LIST_COLUMN);
        String toList = cursor.getString(TO_LIST_COLUMN);
        String ccList = cursor.getString(CC_LIST_COLUMN);
        Address[] fromAddrs = Address.unpack(fromList);
        Address[] toAddrs = Address.unpack(toList);
        Address[] ccAddrs = Address.unpack(ccList);

        boolean fromMe = fragment.messageHelper.toMe(account, fromAddrs);

        CharSequence displayName = fragment.messageHelper.getDisplayName(account, fromAddrs, toAddrs);
        CharSequence displayDate = DateUtils.getRelativeTimeSpanString(context, cursor.getLong(DATE_COLUMN));

        Address counterpartyAddress = fetchCounterPartyAddress(fromMe, toAddrs, ccAddrs, fromAddrs);

        int threadCount = (fragment.showingThreadedList) ? cursor.getInt(THREAD_COUNT_COLUMN) : 0;

        String subject = MlfUtils.buildSubject(cursor.getString(SUBJECT_COLUMN),
                fragment.getString(R.string.general_no_subject), threadCount);

        boolean read = (cursor.getInt(READ_COLUMN) == 1);
        boolean flagged = (cursor.getInt(FLAGGED_COLUMN) == 1);
        boolean answered = (cursor.getInt(ANSWERED_COLUMN) == 1);
        boolean forwarded = (cursor.getInt(FORWARDED_COLUMN) == 1);

        boolean hasAttachments = (cursor.getInt(ATTACHMENT_COUNT_COLUMN) > 0);

        MessageViewHolder holder = (MessageViewHolder) view.getTag();

        // Don't change the text view type face based on unread state
        // use Typeface.NORMAL only (has been hardcoded)
	//int maybeBoldTypeface = (read) ? Typeface.NORMAL : Typeface.BOLD;

        long uniqueId = cursor.getLong(fragment.uniqueIdColumn);
        boolean selected = fragment.selected.contains(uniqueId);

	// If checkboxes are enabled and this email is checked, check the checkbox. #dopetonguetwister
        if (fragment.checkboxes) {
            holder.selected.setChecked(selected);
        }

	// If stars are enabled and this email is starred/flagged, show a 'Star' icon
        if (fragment.stars) {
	    if (flagged)
            {
                holder.starImageView.setVisibility(View.VISIBLE);
            }
            else
            {
                holder.starImageView.setVisibility(View.GONE);
            }
        }
	else
        {
            holder.starImageView.setVisibility(View.GONE);
        }

	// Get the position of this list item
        holder.position = cursor.getPosition();
        if (holder.contactBadge != null) {
            updateContactBadge(holder, counterpartyAddress);
        }
	// Set the background color of this list item
        setBackgroundColor(view, selected, read);

	// I don't really understand this either. PS: I didn't write this code
        if (fragment.activeMessage != null) {
            changeBackgroundColorIfActiveMessage(cursor, account, view);
        }

	// Set the text of the thread count text view
        updateWithThreadCount(holder, threadCount);

	// Set the text of the from text view
        if (holder.from != null)
        {
            holder.from.setTypeface(Typeface.create(holder.from.getTypeface(), Typeface.NORMAL));
            holder.from.setText(displayName);
            holder.from.setVisibility(View.VISIBLE);
	}

	// Set the text of the subject text view
        if (holder.subject != null)
        {
            holder.subject.setTypeface(Typeface.create(holder.subject.getTypeface(), Typeface.NORMAL));
            holder.subject.setText(subject);
            holder.subject.setVisibility(View.VISIBLE);
        }

        // Set the text of the preview text view
        if (fragment.previewLines > 0)
	{
            String preview = getPreview(cursor);

            if (preview != null && !preview.equals(""))
            {
		holder.preview.setMaxLines(fragment.previewLines);
                holder.preview.setText(preview);
                holder.preview.setVisibility(View.VISIBLE);
            }
            else
            {
                holder.preview.setVisibility(View.GONE);
            }
        }

        // Set the text of the date text view
	holder.date.setText(displayDate);

        // If the email has been replied to or has been forwarded, show an icon to indicate that
        Drawable replyStatusHolder = buildStatusHolder(forwarded, answered);

        if (replyStatusHolder != null)
        {
            holder.replyStatusImageView.setImageDrawable(replyStatusHolder);
            holder.replyStatusImageView.setVisibility(View.VISIBLE);
        }
        else
        {
            holder.replyStatusImageView.setVisibility(View.GONE);
        }

	// If the email has any attachments, show an 'Attachment' icon
        if (hasAttachments)
        {
            holder.attachmentImageView.setVisibility(View.VISIBLE);
        }
        else
        {
            holder.attachmentImageView.setVisibility(View.GONE);

        }
    }

    private Address fetchCounterPartyAddress(boolean fromMe, Address[] toAddrs, Address[] ccAddrs, Address[] fromAddrs) {
        if (fromMe) {
            if (toAddrs.length > 0) {
                return toAddrs[0];
            } else if (ccAddrs.length > 0) {
                return ccAddrs[0];
            }
        } else if (fromAddrs.length > 0) {
            return fromAddrs[0];
        }
        return null;
    }

    private void updateContactBadge(MessageViewHolder holder, Address counterpartyAddress) {
        if (counterpartyAddress != null) {
            Utility.setContactForBadge(holder.contactBadge, counterpartyAddress);
                    /*
                     * At least in Android 2.2 a different background + padding is used when no
                     * email address is available. ListView reuses the views but ContactBadge
                     * doesn't reset the padding, so we do it ourselves.
                     */
            holder.contactBadge.setPadding(0, 0, 0, 0);
            fragment.contactsPictureLoader.loadContactPicture(counterpartyAddress, holder.contactBadge);
        } else {
            holder.contactBadge.assignContactUri(null);
            holder.contactBadge.setImageResource(R.drawable.ic_contact_picture);
        }
    }

    private void changeBackgroundColorIfActiveMessage(Cursor cursor, Account account, View view) {
        String uid = cursor.getString(UID_COLUMN);
        String folderName = cursor.getString(FOLDER_NAME_COLUMN);

        if (account.getUuid().equals(fragment.activeMessage.getAccountUuid()) &&
                folderName.equals(fragment.activeMessage.getFolderName()) &&
                uid.equals(fragment.activeMessage.getUid())) {
            int res = R.attr.messageListActiveItemBackgroundColor;

            TypedValue outValue = new TypedValue();
            fragment.getActivity().getTheme().resolveAttribute(res, outValue, true);
            view.setBackgroundColor(outValue.data);
        }
    }

    private Drawable buildStatusHolder(boolean forwarded, boolean answered) {
        if (forwarded && answered) {
            return mForwardedAnsweredIcon;
        } else if (answered) {
            return mAnsweredIcon;
        } else if (forwarded) {
            return mForwardedIcon;
        }
        return null;
    }

    private void setBackgroundColor(View view, boolean selected, boolean read) {
        if (selected || K9.useBackgroundAsUnreadIndicator()) {
            int res;
            if (selected) {
                res = R.attr.messageListSelectedBackgroundColor;
            } else if (read) {
                res = R.attr.messageListReadItemBackgroundColor;
            } else {
                res = R.attr.messageListUnreadItemBackgroundColor;
            }

            TypedValue outValue = new TypedValue();
            fragment.getActivity().getTheme().resolveAttribute(res, outValue, true);
            view.setBackgroundColor(outValue.data);
        } else {
            view.setBackgroundColor(Color.TRANSPARENT);
        }
    }

    private void updateWithThreadCount(MessageViewHolder holder, int threadCount) {
        if (threadCount > 1) {
	    holder.threadCount.setText(String.format(Locale.getDefault(), "%d", threadCount));
            holder.threadCount.setVisibility(View.VISIBLE);
        } else {
            holder.threadCount.setVisibility(View.GONE);
        }
    }

    private String getPreview(Cursor cursor) {
        String previewTypeString = cursor.getString(PREVIEW_TYPE_COLUMN);
        DatabasePreviewType previewType = DatabasePreviewType.fromDatabaseValue(previewTypeString);

        switch (previewType) {
            case NONE:
            case ERROR: {
                return "";
            }
            case ENCRYPTED: {
                return fragment.getString(R.string.preview_encrypted);
            }
            case TEXT: {
                return cursor.getString(PREVIEW_COLUMN);
            }
        }

        throw new AssertionError("Unknown preview type: " + previewType);
    }
}
