/*
 * Copyright (C) 2009 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.contacts;

import com.android.internal.telephony.CallerInfo;

import android.app.ListActivity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.PhoneLookup;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.Contacts.Intents.Insert;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

/**
 * Displays the details of a specific call log entry.
 */
public class CallDetailActivity extends ListActivity implements
        AdapterView.OnItemClickListener {
    private static final String TAG = "CallDetail";

    private TextView mCallType;
    private ImageView mCallTypeIcon;
    private TextView mCallTime;
    private TextView mCallDuration;

    private String mNumber = null;

    /* package */ LayoutInflater mInflater;
    /* package */ Resources mResources;

    static final String[] CALL_LOG_PROJECTION = new String[] {
        CallLog.Calls.DATE,
        CallLog.Calls.DURATION,
        CallLog.Calls.NUMBER,
        CallLog.Calls.TYPE,
    };

    static final int DATE_COLUMN_INDEX = 0;
    static final int DURATION_COLUMN_INDEX = 1;
    static final int NUMBER_COLUMN_INDEX = 2;
    static final int CALL_TYPE_COLUMN_INDEX = 3;

    static final String[] PHONES_PROJECTION = new String[] {
        PhoneLookup._ID,
        PhoneLookup.DISPLAY_NAME,
        PhoneLookup.TYPE,
        PhoneLookup.LABEL,
        PhoneLookup.NUMBER,
    };
    static final int COLUMN_INDEX_ID = 0;
    static final int COLUMN_INDEX_NAME = 1;
    static final int COLUMN_INDEX_TYPE = 2;
    static final int COLUMN_INDEX_LABEL = 3;
    static final int COLUMN_INDEX_NUMBER = 4;

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        setContentView(R.layout.call_detail);

        mInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        mResources = getResources();

        mCallType = (TextView) findViewById(R.id.type);
        mCallTypeIcon = (ImageView) findViewById(R.id.icon);
        mCallTime = (TextView) findViewById(R.id.time);
        mCallDuration = (TextView) findViewById(R.id.duration);

        getListView().setOnItemClickListener(this);
    }

    @Override
    public void onResume() {
        super.onResume();
        updateData(getIntent().getData());
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_CALL: {
                // Make sure phone isn't already busy before starting direct call
                TelephonyManager tm = (TelephonyManager)
                        getSystemService(Context.TELEPHONY_SERVICE);
                if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
                    Intent callIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
                            Uri.fromParts("tel", mNumber, null));
                    startActivity(callIntent);
                    StickyTabs.saveTab(this, getIntent());
                    return true;
                }
            }
        }

        return super.onKeyDown(keyCode, event);
    }

    /**
     * Update user interface with details of given call.
     *
     * @param callUri Uri into {@link CallLog.Calls}
     */
    private void updateData(Uri callUri) {
        ContentResolver resolver = getContentResolver();
        Cursor callCursor = resolver.query(callUri, CALL_LOG_PROJECTION, null, null, null);
        try {
            if (callCursor != null && callCursor.moveToFirst()) {
                // Read call log specifics
                mNumber = callCursor.getString(NUMBER_COLUMN_INDEX);
                long date = callCursor.getLong(DATE_COLUMN_INDEX);
                long duration = callCursor.getLong(DURATION_COLUMN_INDEX);
                int callType = callCursor.getInt(CALL_TYPE_COLUMN_INDEX);

                // Pull out string in format [relative], [date]
                CharSequence dateClause = DateUtils.formatDateRange(this, date, date,
                        DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE |
                        DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_YEAR);
                mCallTime.setText(dateClause);

                // Set the duration
                if (callType == Calls.MISSED_TYPE) {
                    mCallDuration.setVisibility(View.GONE);
                } else {
                    mCallDuration.setVisibility(View.VISIBLE);
                    mCallDuration.setText(formatDuration(duration));
                }

                // Set the call type icon and caption
                String callText = null;
                switch (callType) {
                    case Calls.INCOMING_TYPE:
                        mCallTypeIcon.setImageResource(R.drawable.ic_call_log_header_incoming_call);
                        mCallType.setText(R.string.type_incoming);
                        callText = getString(R.string.callBack);
                        break;

                    case Calls.OUTGOING_TYPE:
                        mCallTypeIcon.setImageResource(R.drawable.ic_call_log_header_outgoing_call);
                        mCallType.setText(R.string.type_outgoing);
                        callText = getString(R.string.callAgain);
                        break;

                    case Calls.MISSED_TYPE:
                        mCallTypeIcon.setImageResource(R.drawable.ic_call_log_header_missed_call);
                        mCallType.setText(R.string.type_missed);
                        callText = getString(R.string.returnCall);
                        break;
                }

                if (mNumber.equals(CallerInfo.UNKNOWN_NUMBER) ||
                        mNumber.equals(CallerInfo.PRIVATE_NUMBER)) {
                    // List is empty, let the empty view show instead.
                    TextView emptyText = (TextView) findViewById(R.id.emptyText);
                    if (emptyText != null) {
                        emptyText.setText(mNumber.equals(CallerInfo.PRIVATE_NUMBER)
                                ? R.string.private_num : R.string.unknown);
                    }
                } else {
                    // Perform a reverse-phonebook lookup to find the PERSON_ID
                    String callLabel = null;
                    Uri personUri = null;
                    Uri phoneUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
                            Uri.encode(mNumber));
                    Cursor phonesCursor = resolver.query(phoneUri, PHONES_PROJECTION, null, null, null);
                    try {
                        if (phonesCursor != null && phonesCursor.moveToFirst()) {
                            long personId = phonesCursor.getLong(COLUMN_INDEX_ID);
                            personUri = ContentUris.withAppendedId(
                                    Contacts.CONTENT_URI, personId);
                            callText = getString(R.string.recentCalls_callNumber,
                                    phonesCursor.getString(COLUMN_INDEX_NAME));
                            mNumber = PhoneNumberUtils.formatNumber(
                                    phonesCursor.getString(COLUMN_INDEX_NUMBER));
                            callLabel = Phone.getDisplayLabel(this,
                                    phonesCursor.getInt(COLUMN_INDEX_TYPE),
                                    phonesCursor.getString(COLUMN_INDEX_LABEL)).toString();
                        } else {
                            mNumber = PhoneNumberUtils.formatNumber(mNumber);
                        }
                    } finally {
                        if (phonesCursor != null) phonesCursor.close();
                    }

                    // Build list of various available actions
                    List<ViewEntry> actions = new ArrayList<ViewEntry>();

                    Intent callIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
                            Uri.fromParts("tel", mNumber, null));
                    ViewEntry entry = new ViewEntry(android.R.drawable.sym_action_call, callText,
                            callIntent);
                    entry.number = mNumber;
                    entry.label = callLabel;
                    actions.add(entry);

                    Intent smsIntent = new Intent(Intent.ACTION_SENDTO,
                            Uri.fromParts("sms", mNumber, null));
                    actions.add(new ViewEntry(R.drawable.sym_action_sms,
                            getString(R.string.menu_sendTextMessage), smsIntent));

                    // Let user view contact details if they exist, otherwise add option
                    // to create new contact from this number.
                    if (personUri != null) {
                        Intent viewIntent = new Intent(Intent.ACTION_VIEW, personUri);
                        StickyTabs.setTab(viewIntent, getIntent());
                        actions.add(new ViewEntry(R.drawable.sym_action_view_contact,
                                getString(R.string.menu_viewContact), viewIntent));
                    } else {
                        Intent createIntent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
                        createIntent.setType(Contacts.CONTENT_ITEM_TYPE);
                        createIntent.putExtra(Insert.PHONE, mNumber);
                        actions.add(new ViewEntry(R.drawable.sym_action_add,
                                getString(R.string.recentCalls_addToContact), createIntent));
                    }

                    ViewAdapter adapter = new ViewAdapter(this, actions);
                    setListAdapter(adapter);
                }
            } else {
                // Something went wrong reading in our primary data, so we're going to
                // bail out and show error to users.
                Toast.makeText(this, R.string.toast_call_detail_error,
                        Toast.LENGTH_SHORT).show();
                finish();
            }
        } finally {
            if (callCursor != null) {
                callCursor.close();
            }
        }
    }

    private String formatDuration(long elapsedSeconds) {
        long minutes = 0;
        long seconds = 0;

        if (elapsedSeconds >= 60) {
            minutes = elapsedSeconds / 60;
            elapsedSeconds -= minutes * 60;
        }
        seconds = elapsedSeconds;

        return getString(R.string.callDetailsDurationFormat, minutes, seconds);
    }

    static final class ViewEntry {
        public int icon = -1;
        public String text = null;
        public Intent intent = null;
        public String label = null;
        public String number = null;

        public ViewEntry(int icon, String text, Intent intent) {
            this.icon = icon;
            this.text = text;
            this.intent = intent;
        }
    }

    static final class ViewAdapter extends BaseAdapter {

        private final List<ViewEntry> mActions;

        private final LayoutInflater mInflater;

        public ViewAdapter(Context context, List<ViewEntry> actions) {
            mActions = actions;
            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        public int getCount() {
            return mActions.size();
        }

        public Object getItem(int position) {
            return mActions.get(position);
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            // Make sure we have a valid convertView to start with
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.call_detail_list_item, parent, false);
            }

            // Fill action with icon and text.
            ViewEntry entry = mActions.get(position);
            convertView.setTag(entry);

            ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
            TextView text = (TextView) convertView.findViewById(android.R.id.text1);

            icon.setImageResource(entry.icon);
            text.setText(entry.text);

            View line2 = convertView.findViewById(R.id.line2);
            boolean numberEmpty = TextUtils.isEmpty(entry.number);
            boolean labelEmpty = TextUtils.isEmpty(entry.label) || numberEmpty;
            if (labelEmpty && numberEmpty) {
                line2.setVisibility(View.GONE);
            } else {
                line2.setVisibility(View.VISIBLE);

                TextView label = (TextView) convertView.findViewById(R.id.label);
                if (labelEmpty) {
                    label.setVisibility(View.GONE);
                } else {
                    label.setText(entry.label);
                    label.setVisibility(View.VISIBLE);
                }

                TextView number = (TextView) convertView.findViewById(R.id.number);
                number.setText(entry.number);
            }

            return convertView;
        }
    }

    public void onItemClick(AdapterView parent, View view, int position, long id) {
        // Handle passing action off to correct handler.
        if (view.getTag() instanceof ViewEntry) {
            ViewEntry entry = (ViewEntry) view.getTag();
            if (entry.intent != null) {
                if (Intent.ACTION_CALL_PRIVILEGED.equals(entry.intent.getAction())) {
                    StickyTabs.saveTab(this, getIntent());
                }
                startActivity(entry.intent);
            }
        }
    }

    @Override
    public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
            boolean globalSearch) {
        if (globalSearch) {
            super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
        } else {
            ContactsSearchManager.startSearch(this, initialQuery);
        }
    }
}
