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

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Message;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.util.Log;
import android.webkit.WebSettingsClassic.AutoFillProfile;

import java.util.concurrent.CountDownLatch;

public class AutofillHandler {

    private AutoFillProfile mAutoFillProfile;
    // Default to zero. In the case no profile is set up, the initial
    // value will come from the AutoFillSettingsFragment when the user
    // creates a profile. Otherwise, we'll read the ID of the last used
    // profile from the prefs db.
    private int mAutoFillActiveProfileId;
    private static final int NO_AUTOFILL_PROFILE_SET = 0;

    private CountDownLatch mLoaded = new CountDownLatch(1);
    private Context mContext;

    private static final String LOGTAG = "AutofillHandler";

    public AutofillHandler(Context context) {
        mContext = context.getApplicationContext();
    }

    /**
     * Load settings from the browser app's database. It is performed in
     * an AsyncTask as it involves plenty of slow disk IO.
     * NOTE: Strings used for the preferences must match those specified
     * in the various preference XML files.
     */
    public void asyncLoadFromDb() {
        // Run the initial settings load in an AsyncTask as it hits the
        // disk multiple times through SharedPreferences and SQLite. We
        // need to be certain though that this has completed before we start
        // to load pages though, so in the worst case we will block waiting
        // for it to finish in BrowserActivity.onCreate().
         new LoadFromDb().start();
    }

    private void waitForLoad() {
        try {
            mLoaded.await();
        } catch (InterruptedException e) {
            Log.w(LOGTAG, "Caught exception while waiting for AutofillProfile to load.");
        }
    }

    private class LoadFromDb extends Thread {

        @Override
        public void run() {
            // Note the lack of synchronization over mAutoFillActiveProfileId and
            // mAutoFillProfile here. This is because we control all other access
            // to these members through the public functions of this class, and they
            // all wait for this thread via the mLoaded CountDownLatch.

            SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(mContext);

            // Read the last active AutoFill profile id.
            mAutoFillActiveProfileId = p.getInt(
                    PreferenceKeys.PREF_AUTOFILL_ACTIVE_PROFILE_ID,
                    mAutoFillActiveProfileId);

            // Load the autofill profile data from the database. We use a database separate
            // to the browser preference DB to make it easier to support multiple profiles
            // and switching between them. Note that this may block startup if this DB lookup
            // is extremely slow. We do this to ensure that if there's a profile set, the
            // user never sees the "setup Autofill" option.
            AutoFillProfileDatabase autoFillDb = AutoFillProfileDatabase.getInstance(mContext);
            Cursor c = autoFillDb.getProfile(mAutoFillActiveProfileId);

            if (c.getCount() > 0) {
                c.moveToFirst();

                String fullName = c.getString(c.getColumnIndex(
                        AutoFillProfileDatabase.Profiles.FULL_NAME));
                String email = c.getString(c.getColumnIndex(
                        AutoFillProfileDatabase.Profiles.EMAIL_ADDRESS));
                String company = c.getString(c.getColumnIndex(
                        AutoFillProfileDatabase.Profiles.COMPANY_NAME));
                String addressLine1 = c.getString(c.getColumnIndex(
                        AutoFillProfileDatabase.Profiles.ADDRESS_LINE_1));
                String addressLine2 = c.getString(c.getColumnIndex(
                        AutoFillProfileDatabase.Profiles.ADDRESS_LINE_2));
                String city = c.getString(c.getColumnIndex(
                        AutoFillProfileDatabase.Profiles.CITY));
                String state = c.getString(c.getColumnIndex(
                        AutoFillProfileDatabase.Profiles.STATE));
                String zip = c.getString(c.getColumnIndex(
                        AutoFillProfileDatabase.Profiles.ZIP_CODE));
                String country = c.getString(c.getColumnIndex(
                        AutoFillProfileDatabase.Profiles.COUNTRY));
                String phone = c.getString(c.getColumnIndex(
                        AutoFillProfileDatabase.Profiles.PHONE_NUMBER));
                mAutoFillProfile = new AutoFillProfile(mAutoFillActiveProfileId,
                        fullName, email, company, addressLine1, addressLine2, city,
                        state, zip, country, phone);
            }
            c.close();
            autoFillDb.close();

            // At this point we've loaded the profile if there was one, so let any thread
            // waiting on initialization continue.
            mLoaded.countDown();

            // Synchronization note: strictly speaking, it's possible that mAutoFillProfile
            // may get a value after we check below, but that's OK. This check is only an
            // optimisation, and we do a proper synchronized check further down when it comes
            // to actually setting the inferred profile.
            if (mAutoFillProfile == null) {
                // We did not load a profile from disk. Try to infer one from the user's
                // "me" contact.
                final Uri profileUri = Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI,
                        ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
                String name = getContactField(profileUri,
                        ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
                // Only attempt to read other data and set a profile if we could successfully
                // get a name.
                if (name != null) {
                    String email = getContactField(profileUri,
                            ContactsContract.CommonDataKinds.Email.ADDRESS,
                            ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
                    String phone = getContactField(profileUri,
                            ContactsContract.CommonDataKinds.Phone.NUMBER,
                            ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
                    String company = getContactField(profileUri,
                            ContactsContract.CommonDataKinds.Organization.COMPANY,
                            ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);

                    // Can't easily get structured postal address information (even using
                    // CommonDataKinds.StructuredPostal) so omit prepopulating that for now.
                    // When querying structured postal data, it often all comes back as a string
                    // inside the "street" field.

                    synchronized(AutofillHandler.this) {
                        // Only use this profile if one hasn't been set inbetween the
                        // inital import and this thread getting to this point.
                        if (mAutoFillProfile == null) {
                            setAutoFillProfile(new AutoFillProfile(1, name, email, company,
                                    null, null, null, null, null, null, phone), null);
                        }
                    }
                }
            }
        }

        private String getContactField(Uri uri, String field, String itemType) {
            String result = null;

            Cursor c = mContext.getContentResolver().query(uri, new String[] { field },
                    ContactsContract.Data.MIMETYPE + "=?", new String[] { itemType }, null);

            if (c == null) {
                return null;
            }

            try {
                // Just use the first returned value if we get more than one.
                if (c.moveToFirst()) {
                    result = c.getString(0);
                }
            } finally {
                c.close();
            }
            return result;
        }
    }

    public synchronized void setAutoFillProfile(AutoFillProfile profile, Message msg) {
        waitForLoad();
        int profileId = NO_AUTOFILL_PROFILE_SET;
        if (profile != null) {
            profileId = profile.getUniqueId();
            // Update the AutoFill DB with the new profile.
            new SaveProfileToDbTask(msg).execute(profile);
        } else {
            // Delete the current profile.
            if (mAutoFillProfile != null) {
                new DeleteProfileFromDbTask(msg).execute(mAutoFillProfile.getUniqueId());
            }
        }
        // Make sure we set mAutoFillProfile before calling setActiveAutoFillProfileId
        // Calling setActiveAutoFillProfileId will trigger an update of WebViews
        // which will expect a new profile to be set
        mAutoFillProfile = profile;
        setActiveAutoFillProfileId(profileId);
    }

    public synchronized AutoFillProfile getAutoFillProfile() {
        waitForLoad();
        return mAutoFillProfile;
    }

    private synchronized void setActiveAutoFillProfileId(int activeProfileId) {
        mAutoFillActiveProfileId = activeProfileId;
        Editor ed = PreferenceManager.
            getDefaultSharedPreferences(mContext).edit();
        ed.putInt(PreferenceKeys.PREF_AUTOFILL_ACTIVE_PROFILE_ID, activeProfileId);
        ed.apply();
    }

    private abstract class AutoFillProfileDbTask<T> extends AsyncTask<T, Void, Void> {
        AutoFillProfileDatabase mAutoFillProfileDb;
        Message mCompleteMessage;

        public AutoFillProfileDbTask(Message msg) {
            mCompleteMessage = msg;
        }

        @Override
        protected void onPostExecute(Void result) {
            if (mCompleteMessage != null) {
                mCompleteMessage.sendToTarget();
            }
            mAutoFillProfileDb.close();
        }

        @Override
        abstract protected Void doInBackground(T... values);
    }


    private class SaveProfileToDbTask extends AutoFillProfileDbTask<AutoFillProfile> {
        public SaveProfileToDbTask(Message msg) {
            super(msg);
        }

        @Override
        protected Void doInBackground(AutoFillProfile... values) {
            mAutoFillProfileDb = AutoFillProfileDatabase.getInstance(mContext);
            synchronized (AutofillHandler.this) {
                assert mAutoFillActiveProfileId != NO_AUTOFILL_PROFILE_SET;
                AutoFillProfile newProfile = values[0];
                mAutoFillProfileDb.addOrUpdateProfile(mAutoFillActiveProfileId, newProfile);
            }
            return null;
        }
    }

    private class DeleteProfileFromDbTask extends AutoFillProfileDbTask<Integer> {
        public DeleteProfileFromDbTask(Message msg) {
            super(msg);
        }

        @Override
        protected Void doInBackground(Integer... values) {
            mAutoFillProfileDb = AutoFillProfileDatabase.getInstance(mContext);
            int id = values[0];
            assert  id > 0;
            mAutoFillProfileDb.dropProfile(id);
            return null;
        }
    }
}
