// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.preferences.autofill;

import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;

import org.chromium.chrome.R;
import org.chromium.chrome.browser.autofill.PersonalDataManager;
import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.AddressField;
import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.AddressUiComponent;
import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.DropdownKeyValue;
import org.chromium.chrome.browser.widget.CompatibilityTextInputLayout;

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

/**
 * Provides the Java-ui for editing a Profile autofill entry.
 */
public class AutofillProfileEditor extends AutofillEditorBase {
    private boolean mNoCountryItemIsSelected;
    private LayoutInflater mInflater;
    private EditText mPhoneText;
    private CompatibilityTextInputLayout mPhoneLabel;
    private EditText mEmailText;
    private CompatibilityTextInputLayout mEmailLabel;
    private String mLanguageCodeString;
    private List<String> mCountryCodes;
    private int mCurrentCountryPos;
    private Spinner mCountriesDropdown;
    private ViewGroup mWidgetRoot;
    private CompatibilityTextInputLayout[] mAddressFields;
    private AutofillProfileBridge mAutofillProfileBridge;
    private boolean mUseSavedProfileLanguage;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = super.onCreateView(inflater, container, savedInstanceState);

        mInflater = inflater;
        mAddressFields = new CompatibilityTextInputLayout[AddressField.NUM_FIELDS];

        mPhoneText = (EditText) v.findViewById(R.id.phone_number_edit);
        mPhoneLabel = (CompatibilityTextInputLayout) v.findViewById(R.id.phone_number_label);
        mEmailText = (EditText) v.findViewById(R.id.email_address_edit);
        mEmailLabel = (CompatibilityTextInputLayout) v.findViewById(R.id.email_address_label);
        mWidgetRoot = (ViewGroup) v.findViewById(R.id.autofill_profile_widget_root);
        mCountriesDropdown = (Spinner) v.findViewById(R.id.spinner);

        TextView countriesLabel = (TextView) v.findViewById(R.id.spinner_label);
        countriesLabel.setText(v.getContext().getString(R.string.autofill_profile_editor_country));

        mAutofillProfileBridge = new AutofillProfileBridge();

        populateCountriesDropdown();
        createAndPopulateEditFields();
        initializeButtons(v);

        return v;
    }

    @Override
    protected int getLayoutId() {
        return R.layout.autofill_profile_editor;
    }

    @Override
    protected int getTitleResourceId(boolean isNewEntry) {
        return isNewEntry ? R.string.autofill_create_profile : R.string.autofill_edit_profile;
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        boolean empty = mNoCountryItemIsSelected && TextUtils.isEmpty(s) && allFieldsEmpty();
        setSaveButtonEnabled(!empty);
    }

    private boolean allFieldsEmpty() {
        if (!TextUtils.isEmpty(mPhoneText.getText())
                || !TextUtils.isEmpty(mEmailText.getText())) {
            return false;
        }
        for (CompatibilityTextInputLayout field : mAddressFields) {
            if (field != null && !TextUtils.isEmpty(field.getEditText().getText())) {
                return false;
            }
        }

        return true;
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        if (position != mCurrentCountryPos) {
            mCurrentCountryPos = position;
            mUseSavedProfileLanguage = false;
            // If all fields are empty (e.g. the user just entered the form and the first thing
            // they did was select a country), focus on the first form element. Otherwise, don't.
            resetFormFields(position, allFieldsEmpty());
            mNoCountryItemIsSelected = false;
            setSaveButtonEnabled(true);
        }
    }

    private void populateCountriesDropdown() {
        List<DropdownKeyValue> countries = AutofillProfileBridge.getSupportedCountries();
        mCountryCodes = new ArrayList<String>();

        for (DropdownKeyValue country : countries) {
            mCountryCodes.add(country.getKey());
        }

        ArrayAdapter<DropdownKeyValue> countriesAdapter = new ArrayAdapter<DropdownKeyValue>(
                getActivity(), android.R.layout.simple_spinner_item, countries);
        countriesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mCountriesDropdown.setAdapter(countriesAdapter);
    }

    private void createAndPopulateEditFields() {
        AutofillProfile profile = PersonalDataManager.getInstance().getProfile(mGUID);

        if (profile != null) {
            if (!TextUtils.isEmpty(profile.getPhoneNumber())) {
                mPhoneLabel.getEditText().setText(profile.getPhoneNumber());
            }

            if (!TextUtils.isEmpty(profile.getEmailAddress())) {
                mEmailLabel.getEditText().setText(profile.getEmailAddress());
            }

            mLanguageCodeString = profile.getLanguageCode();
            mUseSavedProfileLanguage = true;

            mCurrentCountryPos = mCountryCodes.indexOf(profile.getCountryCode());
            if (mCurrentCountryPos == -1) {
                // Use the default country code if profile code is invalid.
                mCurrentCountryPos = mCountryCodes.indexOf(
                        AutofillProfileBridge.getDefaultCountryCode());
                if (mCurrentCountryPos == -1) {
                    // Use the first item in country spinner if the default country code is
                    // invalid.
                    mCurrentCountryPos = 0;
                }
            }

            resetFormFields(mCurrentCountryPos, false);

            setFieldText(AddressField.ADMIN_AREA, profile.getRegion());
            setFieldText(AddressField.LOCALITY, profile.getLocality());
            setFieldText(AddressField.DEPENDENT_LOCALITY, profile.getDependentLocality());
            setFieldText(AddressField.SORTING_CODE, profile.getSortingCode());
            setFieldText(AddressField.POSTAL_CODE, profile.getPostalCode());
            setFieldText(AddressField.STREET_ADDRESS, profile.getStreetAddress());
            setFieldText(AddressField.ORGANIZATION, profile.getCompanyName());
            setFieldText(AddressField.RECIPIENT, profile.getFullName());
        } else {
            mCurrentCountryPos = mCountryCodes.indexOf(
                    AutofillProfileBridge.getDefaultCountryCode());
            if (mCurrentCountryPos == -1) {
                // Use the first item in country spinner if the default country code is
                // invalid.
                mCurrentCountryPos = 0;
            }
            resetFormFields(mCurrentCountryPos, true);
        }

        mCountriesDropdown.setSelection(mCurrentCountryPos);
    }

    private void resetFormFields(int countryCodeIndex, boolean autoFocusFirstField) {
        // Save field text so we can restore it after updating the fields for the current country,
        // and reset mAddressFields.
        String[] fieldText = new String[mAddressFields.length];
        for (int i = 0; i < mAddressFields.length; i++) {
            if (mAddressFields[i] != null) {
                fieldText[i] = mAddressFields[i].getEditText().getText().toString();
                mAddressFields[i] = null;
            }
        }

        // Remove all address form fields.
        mWidgetRoot.removeAllViews();

        // Get address fields for the selected country.
        List<AddressUiComponent> fields = mAutofillProfileBridge.getAddressUiComponents(
                mCountryCodes.get(countryCodeIndex),
                mLanguageCodeString);
        if (!mUseSavedProfileLanguage) {
            mLanguageCodeString = mAutofillProfileBridge.getCurrentBestLanguageCode();
        }

        // Create form fields and focus the first field if autoFocusFirstField is true.
        boolean firstField = true;
        for (AddressUiComponent field : fields) {
            CompatibilityTextInputLayout fieldFloatLabel =
                    (CompatibilityTextInputLayout) mInflater.inflate(
                            R.layout.preference_address_float_label_layout, mWidgetRoot, false);
            fieldFloatLabel.setHint(field.label);

            EditText fieldEditText = fieldFloatLabel.getEditText();
            fieldEditText.addTextChangedListener(this);
            if (field.id == AddressField.STREET_ADDRESS) {
                fieldEditText.setSingleLine(false);
            }

            mAddressFields[field.id] = fieldFloatLabel;
            mWidgetRoot.addView(fieldFloatLabel);

            if (firstField && autoFocusFirstField) {
                fieldEditText.requestFocus();
                firstField = false;
            }
        }

        // Add back saved field text.
        for (int i = 0; i < mAddressFields.length; i++) {
            if (mAddressFields[i] != null && fieldText[i] != null
                    && !TextUtils.isEmpty(fieldText[i])) {
                mAddressFields[i].getEditText().setText(fieldText[i]);
            }
        }
    }

    // Read edited data; save in the associated Chrome profile.
    // Ignore empty fields.
    @Override
    protected boolean saveEntry() {
        AutofillProfile profile = new PersonalDataManager.AutofillProfile(mGUID,
                AutofillPreferences.SETTINGS_ORIGIN, true /* isLocal */,
                getFieldText(AddressField.RECIPIENT), getFieldText(AddressField.ORGANIZATION),
                getFieldText(AddressField.STREET_ADDRESS), getFieldText(AddressField.ADMIN_AREA),
                getFieldText(AddressField.LOCALITY), getFieldText(AddressField.DEPENDENT_LOCALITY),
                getFieldText(AddressField.POSTAL_CODE), getFieldText(AddressField.SORTING_CODE),
                mCountryCodes.get(mCurrentCountryPos), mPhoneText.getText().toString(),
                mEmailText.getText().toString(), mLanguageCodeString);
        PersonalDataManager.getInstance().setProfile(profile);
        return true;
    }

    private String getFieldText(int fieldId) {
        if (mAddressFields[fieldId] != null) {
            return mAddressFields[fieldId].getEditText().getText().toString();
        }
        return null;
    }

    private void setFieldText(int fieldId, String text) {
        if (mAddressFields[fieldId] != null && !TextUtils.isEmpty(text)) {
            mAddressFields[fieldId].getEditText().setText(text);
        }
    }

    @Override
    protected void deleteEntry() {
        if (mGUID != null) {
            PersonalDataManager.getInstance().deleteProfile(mGUID);
        }
    }

    @Override
    protected void initializeButtons(View v) {
        super.initializeButtons(v);

        // Listen for changes to inputs. Enable the save button after something has changed.
        mPhoneText.addTextChangedListener(this);
        mEmailText.addTextChangedListener(this);
        mCountriesDropdown.setOnItemSelectedListener(this);
        mNoCountryItemIsSelected = true;

        // Listen for touch events on country field. We clear the keyboard when user touches
        // the country field because it is a drop down menu.
        mCountriesDropdown.setOnTouchListener(this);
    }

    private void setSaveButtonEnabled(boolean enabled) {
        if (getView() != null) {
            Button button = (Button) getView().findViewById(R.id.button_primary);
            button.setEnabled(enabled);
        }
    }
}