// Copyright (c) 2011 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.

#include "chrome/browser/autofill/autofill_profile.h"

#include <algorithm>
#include <map>
#include <set>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/autofill/address.h"
#include "chrome/browser/autofill/autofill_type.h"
#include "chrome/browser/autofill/contact_info.h"
#include "chrome/browser/autofill/fax_number.h"
#include "chrome/browser/autofill/home_phone_number.h"
#include "chrome/common/guid.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

namespace {

// Like |AutofillType::GetEquivalentFieldType()|, but also returns |NAME_FULL|
// for first, middle, and last name field types.
AutofillFieldType GetEquivalentFieldTypeCollapsingNames(
    AutofillFieldType field_type) {
  if (field_type == NAME_FIRST || field_type == NAME_MIDDLE ||
      field_type == NAME_LAST)
    return NAME_FULL;

  return AutofillType::GetEquivalentFieldType(field_type);
}

// Fills |distinguishing_fields| with a list of fields to use when creating
// labels that can help to distinguish between two profiles. Draws fields from
// |suggested_fields| if it is non-NULL; otherwise returns a default list.
// If |suggested_fields| is non-NULL, does not include |excluded_field| in the
// list. Otherwise, |excluded_field| is ignored, and should be set to
// |UNKNOWN_TYPE| by convention. The resulting list of fields is sorted in
// decreasing order of importance.
void GetFieldsForDistinguishingProfiles(
    const std::vector<AutofillFieldType>* suggested_fields,
    AutofillFieldType excluded_field,
    std::vector<AutofillFieldType>* distinguishing_fields) {
  static const AutofillFieldType kDefaultDistinguishingFields[] = {
    NAME_FULL,
    ADDRESS_HOME_LINE1,
    ADDRESS_HOME_CITY,
    ADDRESS_HOME_STATE,
    ADDRESS_HOME_ZIP,
    ADDRESS_HOME_COUNTRY,
    EMAIL_ADDRESS,
    PHONE_HOME_WHOLE_NUMBER,
    PHONE_FAX_WHOLE_NUMBER,
    COMPANY_NAME,
  };

  if (!suggested_fields) {
    DCHECK_EQ(excluded_field, UNKNOWN_TYPE);
    distinguishing_fields->assign(
        kDefaultDistinguishingFields,
        kDefaultDistinguishingFields + arraysize(kDefaultDistinguishingFields));
    return;
  }

  // Keep track of which fields we've seen so that we avoid duplicate entries.
  // Always ignore fields of unknown type and the excluded field.
  std::set<AutofillFieldType> seen_fields;
  seen_fields.insert(UNKNOWN_TYPE);
  seen_fields.insert(GetEquivalentFieldTypeCollapsingNames(excluded_field));

  distinguishing_fields->clear();
  for (std::vector<AutofillFieldType>::const_iterator it =
           suggested_fields->begin();
       it != suggested_fields->end(); ++it) {
    AutofillFieldType suggested_type =
        GetEquivalentFieldTypeCollapsingNames(*it);
    if (seen_fields.insert(suggested_type).second)
      distinguishing_fields->push_back(suggested_type);
  }

  // Special case: If the excluded field is a partial name (e.g. first name) and
  // the suggested fields include other name fields, include |NAME_FULL| in the
  // list of distinguishing fields as a last-ditch fallback. This allows us to
  // distinguish between profiles that are identical except for the name.
  if (excluded_field != NAME_FULL &&
      GetEquivalentFieldTypeCollapsingNames(excluded_field) == NAME_FULL) {
    for (std::vector<AutofillFieldType>::const_iterator it =
             suggested_fields->begin();
         it != suggested_fields->end(); ++it) {
      if (*it != excluded_field &&
          GetEquivalentFieldTypeCollapsingNames(*it) == NAME_FULL) {
        distinguishing_fields->push_back(NAME_FULL);
        break;
      }
    }
  }
}

// A helper function for string streaming.  Concatenates multi-valued entries
// stored for a given |type| into a single string.  This string is returned.
const string16 MultiString(const AutofillProfile& p, AutofillFieldType type) {
  std::vector<string16> values;
  p.GetMultiInfo(type, &values);
  string16 accumulate;
  for (size_t i = 0; i < values.size(); ++i) {
    if (i > 0)
      accumulate += ASCIIToUTF16(" ");
    accumulate += values[i];
  }
  return accumulate;
}

template <class T>
void CopyValuesToItems(AutofillFieldType type,
                       const std::vector<string16>& values,
                       std::vector<T>* form_group_items) {
  form_group_items->resize(values.size());
  for (size_t i = 0; i < form_group_items->size(); ++i)
    (*form_group_items)[i].SetInfo(type, CollapseWhitespace(values[i], false));
  // Must have at least one (possibly empty) element.
  if (form_group_items->empty())
    form_group_items->resize(1);
}

template <class T>
void CopyItemsToValues(AutofillFieldType type,
                       const std::vector<T>& form_group_items,
                       std::vector<string16>* values) {
  values->resize(form_group_items.size());
  for (size_t i = 0; i < values->size(); ++i)
    (*values)[i] = form_group_items[i].GetInfo(type);
}

// Collapse compound field types to their "full" type.  I.e. First name
// collapses to full name, area code collapses to full phone, etc.
void CollapseCompoundFieldTypes(FieldTypeSet* type_set) {
  FieldTypeSet collapsed_set;
  for (FieldTypeSet::iterator iter = type_set->begin(); iter != type_set->end();
       ++iter) {
    switch (*iter) {
      case NAME_FIRST:
      case NAME_MIDDLE:
      case NAME_LAST:
      case NAME_MIDDLE_INITIAL:
      case NAME_FULL:
      case NAME_SUFFIX:
        collapsed_set.insert(NAME_FULL);
        break;

      case PHONE_HOME_NUMBER:
      case PHONE_HOME_CITY_CODE:
      case PHONE_HOME_COUNTRY_CODE:
      case PHONE_HOME_CITY_AND_NUMBER:
      case PHONE_HOME_WHOLE_NUMBER:
        collapsed_set.insert(PHONE_HOME_WHOLE_NUMBER);
        break;

      case PHONE_FAX_NUMBER:
      case PHONE_FAX_CITY_CODE:
      case PHONE_FAX_COUNTRY_CODE:
      case PHONE_FAX_CITY_AND_NUMBER:
      case PHONE_FAX_WHOLE_NUMBER:
        collapsed_set.insert(PHONE_FAX_WHOLE_NUMBER);
        break;

      default:
        collapsed_set.insert(*iter);
    }
  }
  std::swap(*type_set, collapsed_set);
}

}  // namespace

AutofillProfile::AutofillProfile(const std::string& guid)
    : guid_(guid), name_(1), email_(1), home_number_(1), fax_number_(1) {
}

AutofillProfile::AutofillProfile()
    : guid_(guid::GenerateGUID()),
      name_(1),
      email_(1),
      home_number_(1),
      fax_number_(1) {
}

AutofillProfile::AutofillProfile(const AutofillProfile& profile)
    : FormGroup() {
  operator=(profile);
}

AutofillProfile::~AutofillProfile() {
}

AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) {
  if (this == &profile)
    return *this;

  label_ = profile.label_;
  guid_ = profile.guid_;

  name_ = profile.name_;
  email_ = profile.email_;
  company_ = profile.company_;
  home_number_ = profile.home_number_;
  fax_number_ = profile.fax_number_;
  address_ = profile.address_;

  return *this;
}

void AutofillProfile::GetPossibleFieldTypes(
    const string16& text,
    FieldTypeSet* possible_types) const {
  FormGroupList info = FormGroups();
  for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
    (*it)->GetPossibleFieldTypes(text, possible_types);
}

void AutofillProfile::GetAvailableFieldTypes(
    FieldTypeSet* available_types) const {
  FormGroupList info = FormGroups();
  for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
    (*it)->GetAvailableFieldTypes(available_types);
}

string16 AutofillProfile::GetInfo(AutofillFieldType type) const {
  AutofillFieldType return_type = AutofillType::GetEquivalentFieldType(type);
  const FormGroup* form_group = FormGroupForType(return_type);
  if (!form_group)
    return string16();

  return form_group->GetInfo(return_type);
}

void AutofillProfile::SetInfo(AutofillFieldType type, const string16& value) {
  FormGroup* form_group = MutableFormGroupForType(type);
  if (form_group)
    form_group->SetInfo(type, CollapseWhitespace(value, false));
}

void AutofillProfile::SetMultiInfo(AutofillFieldType type,
                                   const std::vector<string16>& values) {
  switch (AutofillType(type).group()) {
    case AutofillType::NAME:
      CopyValuesToItems(type, values, &name_);
      break;
    case AutofillType::EMAIL:
      CopyValuesToItems(type, values, &email_);
      break;
    case AutofillType::PHONE_HOME:
      CopyValuesToItems(type, values, &home_number_);
      break;
    case AutofillType::PHONE_FAX:
      CopyValuesToItems(type, values, &fax_number_);
      break;
    default:
      if (values.size() == 1) {
        SetInfo(type, values[0]);
      } else if (values.size() == 0) {
        SetInfo(type, string16());
      } else {
        NOTREACHED()
            << "Attempt to set multiple values on single-valued field.";
      }
      break;
  }
}

void AutofillProfile::GetMultiInfo(AutofillFieldType type,
                                   std::vector<string16>* values) const {
  switch (AutofillType(type).group()) {
    case AutofillType::NAME:
      CopyItemsToValues(type, name_, values);
      break;
    case AutofillType::EMAIL:
      CopyItemsToValues(type, email_, values);
      break;
    case AutofillType::PHONE_HOME:
      CopyItemsToValues(type, home_number_, values);
      break;
    case AutofillType::PHONE_FAX:
      CopyItemsToValues(type, fax_number_, values);
      break;
    default:
      values->resize(1);
      (*values)[0] = GetInfo(type);
  }
}

// static
bool AutofillProfile::SupportsMultiValue(AutofillFieldType type) {
  AutofillType::FieldTypeGroup group = AutofillType(type).group();
  return group == AutofillType::NAME ||
         group == AutofillType::EMAIL ||
         group == AutofillType::PHONE_HOME ||
         group == AutofillType::PHONE_FAX;
}

const string16 AutofillProfile::Label() const {
  return label_;
}

const std::string AutofillProfile::CountryCode() const {
  return address_.country_code();
}

void AutofillProfile::SetCountryCode(const std::string& country_code) {
  address_.set_country_code(country_code);
}

// static
bool AutofillProfile::AdjustInferredLabels(
    std::vector<AutofillProfile*>* profiles) {
  const size_t kMinimalFieldsShown = 2;

  std::vector<string16> created_labels;
  CreateInferredLabels(profiles, NULL, UNKNOWN_TYPE, kMinimalFieldsShown,
                       &created_labels);
  DCHECK_EQ(profiles->size(), created_labels.size());

  bool updated_labels = false;
  for (size_t i = 0; i < profiles->size(); ++i) {
    if ((*profiles)[i]->Label() != created_labels[i]) {
      updated_labels = true;
      (*profiles)[i]->label_ = created_labels[i];
    }
  }
  return updated_labels;
}

// static
void AutofillProfile::CreateInferredLabels(
    const std::vector<AutofillProfile*>* profiles,
    const std::vector<AutofillFieldType>* suggested_fields,
    AutofillFieldType excluded_field,
    size_t minimal_fields_shown,
    std::vector<string16>* created_labels) {
  DCHECK(profiles);
  DCHECK(created_labels);

  std::vector<AutofillFieldType> fields_to_use;
  GetFieldsForDistinguishingProfiles(suggested_fields, excluded_field,
                                     &fields_to_use);

  // Construct the default label for each profile. Also construct a map that
  // associates each label with the profiles that have this label. This map is
  // then used to detect which labels need further differentiating fields.
  std::map<string16, std::list<size_t> > labels;
  for (size_t i = 0; i < profiles->size(); ++i) {
    string16 label =
        (*profiles)[i]->ConstructInferredLabel(fields_to_use,
                                               minimal_fields_shown);
    labels[label].push_back(i);
  }

  created_labels->resize(profiles->size());
  for (std::map<string16, std::list<size_t> >::const_iterator it =
           labels.begin();
       it != labels.end(); ++it) {
    if (it->second.size() == 1) {
      // This label is unique, so use it without any further ado.
      string16 label = it->first;
      size_t profile_index = it->second.front();
      (*created_labels)[profile_index] = label;
    } else {
      // We have more than one profile with the same label, so add
      // differentiating fields.
      CreateDifferentiatingLabels(*profiles, it->second, fields_to_use,
                                  minimal_fields_shown, created_labels);
    }
  }
}

bool AutofillProfile::IsEmpty() const {
  FieldTypeSet types;
  GetAvailableFieldTypes(&types);
  return types.empty();
}

int AutofillProfile::Compare(const AutofillProfile& profile) const {
  // The following Autofill field types are the only types we store in the WebDB
  // so far, so we're only concerned with matching these types in the profile.
  const AutofillFieldType types[] = { NAME_FIRST,
                                      NAME_MIDDLE,
                                      NAME_LAST,
                                      EMAIL_ADDRESS,
                                      COMPANY_NAME,
                                      ADDRESS_HOME_LINE1,
                                      ADDRESS_HOME_LINE2,
                                      ADDRESS_HOME_CITY,
                                      ADDRESS_HOME_STATE,
                                      ADDRESS_HOME_ZIP,
                                      ADDRESS_HOME_COUNTRY,
                                      PHONE_HOME_NUMBER,
                                      PHONE_FAX_NUMBER };

  for (size_t index = 0; index < arraysize(types); ++index) {
    int comparison = GetInfo(types[index]).compare(
        profile.GetInfo(types[index]));
    if (comparison != 0)
      return comparison;
  }

  return 0;
}

int AutofillProfile::CompareMulti(const AutofillProfile& profile) const {
  const AutofillFieldType single_value_types[] = { COMPANY_NAME,
                                                   ADDRESS_HOME_LINE1,
                                                   ADDRESS_HOME_LINE2,
                                                   ADDRESS_HOME_CITY,
                                                   ADDRESS_HOME_STATE,
                                                   ADDRESS_HOME_ZIP,
                                                   ADDRESS_HOME_COUNTRY };

  for (size_t i = 0; i < arraysize(single_value_types); ++i) {
    int comparison = GetInfo(single_value_types[i]).compare(
        profile.GetInfo(single_value_types[i]));
    if (comparison != 0)
      return comparison;
  }

  const AutofillFieldType multi_value_types[] = { NAME_FIRST,
                                                  NAME_MIDDLE,
                                                  NAME_LAST,
                                                  EMAIL_ADDRESS,
                                                  PHONE_HOME_NUMBER,
                                                  PHONE_FAX_NUMBER };

  for (size_t i = 0; i < arraysize(multi_value_types); ++i) {
    std::vector<string16> values_a;
    std::vector<string16> values_b;
    GetMultiInfo(multi_value_types[i], &values_a);
    profile.GetMultiInfo(multi_value_types[i], &values_b);
    if (values_a.size() < values_b.size())
      return -1;
    if (values_a.size() > values_b.size())
      return 1;
    for (size_t j = 0; j < values_a.size(); ++j) {
      int comparison = values_a[j].compare(values_b[j]);
      if (comparison != 0)
        return comparison;
    }
  }

  return 0;
}

bool AutofillProfile::operator==(const AutofillProfile& profile) const {
  return guid_ == profile.guid_ && Compare(profile) == 0;
}

bool AutofillProfile::operator!=(const AutofillProfile& profile) const {
  return !operator==(profile);
}

const string16 AutofillProfile::PrimaryValue() const {
  return GetInfo(ADDRESS_HOME_LINE1) +
         GetInfo(ADDRESS_HOME_CITY);
}

void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) {
  FieldTypeSet field_types;
  profile.GetAvailableFieldTypes(&field_types);

  // Only transfer "full" types (e.g. full name) and not fragments (e.g.
  // first name, last name).
  CollapseCompoundFieldTypes(&field_types);

  for (FieldTypeSet::const_iterator iter = field_types.begin();
       iter != field_types.end(); ++iter) {
    if (AutofillProfile::SupportsMultiValue(*iter)) {
      std::vector<string16> new_values;
      profile.GetMultiInfo(*iter, &new_values);
      std::vector<string16> existing_values;
      GetMultiInfo(*iter, &existing_values);
      for (std::vector<string16>::iterator value_iter = new_values.begin();
           value_iter != new_values.end(); ++value_iter) {
        // Don't add duplicates.
        if (std::find(existing_values.begin(), existing_values.end(),
                      *value_iter) == existing_values.end()) {
          existing_values.insert(existing_values.end(), *value_iter);
        }
      }
      SetMultiInfo(*iter, existing_values);
    } else {
      SetInfo(*iter, profile.GetInfo(*iter));
    }
  }
}

string16 AutofillProfile::ConstructInferredLabel(
    const std::vector<AutofillFieldType>& included_fields,
    size_t num_fields_to_use) const {
  const string16 separator =
      l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR);

  string16 label;
  size_t num_fields_used = 0;
  for (std::vector<AutofillFieldType>::const_iterator it =
           included_fields.begin();
       it != included_fields.end() && num_fields_used < num_fields_to_use;
       ++it) {
    string16 field = GetInfo(*it);
    if (field.empty())
      continue;

    if (!label.empty())
      label.append(separator);

#ifndef ANDROID
    // Fax number has special format, to indicate that this is a fax number.
    if (*it == PHONE_FAX_WHOLE_NUMBER) {
      field = l10n_util::GetStringFUTF16(
          IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_FAX_FORMAT, field);
    }
#endif
    label.append(field);
    ++num_fields_used;
  }
  return label;
}

// static
void AutofillProfile::CreateDifferentiatingLabels(
    const std::vector<AutofillProfile*>& profiles,
    const std::list<size_t>& indices,
    const std::vector<AutofillFieldType>& fields,
    size_t num_fields_to_include,
    std::vector<string16>* created_labels) {
  // For efficiency, we first construct a map of fields to their text values and
  // each value's frequency.
  std::map<AutofillFieldType,
           std::map<string16, size_t> > field_text_frequencies_by_field;
  for (std::vector<AutofillFieldType>::const_iterator field = fields.begin();
       field != fields.end(); ++field) {
    std::map<string16, size_t>& field_text_frequencies =
        field_text_frequencies_by_field[*field];

    for (std::list<size_t>::const_iterator it = indices.begin();
         it != indices.end(); ++it) {
      const AutofillProfile* profile = profiles[*it];
      string16 field_text = profile->GetInfo(*field);

      // If this label is not already in the map, add it with frequency 0.
      if (!field_text_frequencies.count(field_text))
        field_text_frequencies[field_text] = 0;

      // Now, increment the frequency for this label.
      ++field_text_frequencies[field_text];
    }
  }

  // Now comes the meat of the algorithm. For each profile, we scan the list of
  // fields to use, looking for two things:
  //  1. A (non-empty) field that differentiates the profile from all others
  //  2. At least |num_fields_to_include| non-empty fields
  // Before we've satisfied condition (2), we include all fields, even ones that
  // are identical across all the profiles. Once we've satisfied condition (2),
  // we only include fields that that have at last two distinct values.
  for (std::list<size_t>::const_iterator it = indices.begin();
       it != indices.end(); ++it) {
    const AutofillProfile* profile = profiles[*it];

    std::vector<AutofillFieldType> label_fields;
    bool found_differentiating_field = false;
    for (std::vector<AutofillFieldType>::const_iterator field = fields.begin();
         field != fields.end(); ++field) {
      // Skip over empty fields.
      string16 field_text = profile->GetInfo(*field);
      if (field_text.empty())
        continue;

      std::map<string16, size_t>& field_text_frequencies =
          field_text_frequencies_by_field[*field];
      found_differentiating_field |=
          !field_text_frequencies.count(string16()) &&
          (field_text_frequencies[field_text] == 1);

      // Once we've found enough non-empty fields, skip over any remaining
      // fields that are identical across all the profiles.
      if (label_fields.size() >= num_fields_to_include &&
          (field_text_frequencies.size() == 1))
        continue;

      label_fields.push_back(*field);

      // If we've (1) found a differentiating field and (2) found at least
      // |num_fields_to_include| non-empty fields, we're done!
      if (found_differentiating_field &&
          label_fields.size() >= num_fields_to_include)
        break;
    }

    (*created_labels)[*it] =
        profile->ConstructInferredLabel(label_fields,
                                        label_fields.size());
  }
}

AutofillProfile::FormGroupList AutofillProfile::FormGroups() const {
  FormGroupList v(6);
  v[0] = &name_[0];
  v[1] = &email_[0];
  v[2] = &company_;
  v[3] = &home_number_[0];
  v[4] = &fax_number_[0];
  v[5] = &address_;
  return v;
}

const FormGroup* AutofillProfile::FormGroupForType(
    AutofillFieldType type) const {
  return const_cast<AutofillProfile*>(this)->MutableFormGroupForType(type);
}

FormGroup* AutofillProfile::MutableFormGroupForType(AutofillFieldType type) {
 FormGroup* form_group = NULL;
  switch (AutofillType(type).group()) {
    case AutofillType::NAME:
      form_group = &name_[0];
      break;
    case AutofillType::EMAIL:
      form_group = &email_[0];
      break;
    case AutofillType::COMPANY:
      form_group = &company_;
      break;
    case AutofillType::PHONE_HOME:
      form_group = &home_number_[0];
      break;
    case AutofillType::PHONE_FAX:
      form_group = &fax_number_[0];
      break;
    case AutofillType::ADDRESS_HOME:
      form_group = &address_;
      break;
    default:
      break;
  }
  return form_group;
}

// So we can compare AutofillProfiles with EXPECT_EQ().
std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
  return os
      << UTF16ToUTF8(profile.Label())
      << " "
      << profile.guid()
      << " "
      << UTF16ToUTF8(MultiString(profile, NAME_FIRST))
      << " "
      << UTF16ToUTF8(MultiString(profile, NAME_MIDDLE))
      << " "
      << UTF16ToUTF8(MultiString(profile, NAME_LAST))
      << " "
      << UTF16ToUTF8(MultiString(profile, EMAIL_ADDRESS))
      << " "
      << UTF16ToUTF8(profile.GetInfo(COMPANY_NAME))
      << " "
      << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_LINE1))
      << " "
      << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_LINE2))
      << " "
      << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_CITY))
      << " "
      << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_STATE))
      << " "
      << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_ZIP))
      << " "
      << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_COUNTRY))
      << " "
      << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER))
      << " "
      << UTF16ToUTF8(MultiString(profile, PHONE_FAX_WHOLE_NUMBER));
}
