// 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/contact_info.h"

#include <stddef.h>
#include <ostream>
#include <string>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/autofill/autofill_type.h"
#include "chrome/browser/autofill/field_types.h"

static const string16 kNameSplitChars = ASCIIToUTF16("-'. ");

static const AutofillFieldType kAutofillNameInfoTypes[] = {
  NAME_FIRST,
  NAME_MIDDLE,
  NAME_LAST
};

static const size_t kAutofillNameInfoLength =
    arraysize(kAutofillNameInfoTypes);

NameInfo::NameInfo() {}

NameInfo::NameInfo(const NameInfo& info) : FormGroup() {
  *this = info;
}

NameInfo::~NameInfo() {}

NameInfo& NameInfo::operator=(const NameInfo& info) {
  if (this == &info)
    return *this;

  first_tokens_ = info.first_tokens_;
  middle_tokens_ = info.middle_tokens_;
  last_tokens_ = info.last_tokens_;
  first_ = info.first_;
  middle_ = info.middle_;
  last_ = info.last_;
  return *this;
}

void NameInfo::GetPossibleFieldTypes(const string16& text,
                                        FieldTypeSet* possible_types) const {
  DCHECK(possible_types);

  if (IsFirstName(text))
    possible_types->insert(NAME_FIRST);

  if (IsMiddleName(text))
    possible_types->insert(NAME_MIDDLE);

  if (IsLastName(text))
    possible_types->insert(NAME_LAST);

  if (IsMiddleInitial(text))
    possible_types->insert(NAME_MIDDLE_INITIAL);

  if (IsFullName(text))
    possible_types->insert(NAME_FULL);
}

void NameInfo::GetAvailableFieldTypes(FieldTypeSet* available_types) const {
  DCHECK(available_types);

  if (!first().empty())
    available_types->insert(NAME_FIRST);

  if (!middle().empty())
    available_types->insert(NAME_MIDDLE);

  if (!last().empty())
    available_types->insert(NAME_LAST);

  if (!MiddleInitial().empty())
    available_types->insert(NAME_MIDDLE_INITIAL);

  if (!FullName().empty())
    available_types->insert(NAME_FULL);
}

string16 NameInfo::GetInfo(AutofillFieldType type) const {
  if (type == NAME_FIRST)
    return first();

  if (type == NAME_MIDDLE)
    return middle();

  if (type == NAME_LAST)
    return last();

  if (type == NAME_MIDDLE_INITIAL)
    return MiddleInitial();

  if (type == NAME_FULL)
    return FullName();

  return string16();
}

void NameInfo::SetInfo(AutofillFieldType type, const string16& value) {
  DCHECK_EQ(AutofillType::NAME, AutofillType(type).group());
  if (type == NAME_FIRST)
    SetFirst(value);
  else if (type == NAME_MIDDLE || type == NAME_MIDDLE_INITIAL)
    SetMiddle(value);
  else if (type == NAME_LAST)
    SetLast(value);
  else if (type == NAME_FULL)
    SetFullName(value);
  else
    NOTREACHED();
}

string16 NameInfo::FullName() const {
  if (first_.empty())
    return string16();

  std::vector<string16> full_name;
  full_name.push_back(first_);

  if (!middle_.empty())
    full_name.push_back(middle_);

  if (!last_.empty())
    full_name.push_back(last_);

  return JoinString(full_name, ' ');
}

string16 NameInfo::MiddleInitial() const {
  if (middle_.empty())
    return string16();

  string16 middle_name(middle());
  string16 initial;
  initial.push_back(middle_name[0]);
  return initial;
}

// If each of the 'words' contained in the text are also present in the first
// name then we will consider the text to be of type kFirstName. This means
// that people with multiple first names will be able to enter any one of
// their first names and have it correctly recognized.
bool NameInfo::IsFirstName(const string16& text) const {
  return IsNameMatch(text, first_tokens_);
}

// If each of the 'words' contained in the text are also present in the middle
// name then we will consider the text to be of type kMiddleName.
bool NameInfo::IsMiddleName(const string16& text) const {
  return IsNameMatch(text, middle_tokens_);
}

// If each of the 'words' contained in the text are also present in the last
// name then we will consider the text to be of type kLastName.
bool NameInfo::IsLastName(const string16& text) const {
  return IsNameMatch(text, last_tokens_);
}

bool NameInfo::IsMiddleInitial(const string16& text) const {
  if (text.length() != 1)
     return false;

  string16 lower_case = StringToLowerASCII(text);
  // If the text entered was a single character and it matches the first letter
  // of any of the given middle names then we consider it to be a middle
  // initial field.
  size_t middle_tokens_size = middle_tokens_.size();
  for (size_t i = 0; i < middle_tokens_size; ++i) {
    if (middle_tokens_[i][0] == lower_case[0])
      return true;
  }

  return false;
}

// A field will be considered to be of type NAME_FULL if:
//    1) it contains at least one word from the first name.
//    2) it contains at least one word from the last name.
//    3) all of the words in the field match a word in either the first,
//       middle, or last name.
bool NameInfo::IsFullName(const string16& text) const {
  size_t first_tokens_size = first_tokens_.size();
  if (first_tokens_size == 0)
    return false;

  size_t middle_tokens_size = middle_tokens_.size();

  size_t last_tokens_size = last_tokens_.size();
  if (last_tokens_size == 0)
    return false;

  std::vector<string16> text_tokens;
  Tokenize(text, kNameSplitChars, &text_tokens);
  size_t text_tokens_size = text_tokens.size();
  if (text_tokens_size == 0 || text_tokens_size < 2)
    return false;

  size_t name_tokens_size =
      first_tokens_size + middle_tokens_size + last_tokens_size;
  if (text_tokens_size > name_tokens_size)
    return false;

  bool first_name_match = false;
  bool last_name_match = false;
  for (std::vector<string16>::iterator iter = text_tokens.begin();
       iter != text_tokens.end(); ++iter) {
    bool match = false;
    if (IsWordInName(*iter, first_tokens_)) {
      match = true;
      first_name_match = true;
    }

    if (IsWordInName(*iter, last_tokens_)) {
      match = true;
      last_name_match = true;
    }

    if (IsWordInName(*iter, middle_tokens_))
      match = true;

    if (!match)
      return false;
  }

  return (first_name_match && last_name_match);
}

bool NameInfo::IsNameMatch(const string16& text,
                           const std::vector<string16>& name_tokens) const {
  size_t name_tokens_size = name_tokens.size();
  if (name_tokens_size == 0)
    return false;

  std::vector<string16> text_tokens;
  Tokenize(text, kNameSplitChars, &text_tokens);
  size_t text_tokens_size = text_tokens.size();
  if (text_tokens_size == 0)
    return false;

  if (text_tokens_size > name_tokens_size)
    return false;

  // If each of the 'words' contained in the text are also present in the name,
  // then we will consider the text to match the name.
  for (std::vector<string16>::iterator iter = text_tokens.begin();
       iter != text_tokens.end(); ++iter) {
    if (!IsWordInName(*iter, name_tokens))
      return false;
  }

  return true;
}

bool NameInfo::IsWordInName(const string16& word,
                            const std::vector<string16>& name_tokens) const {
  for (std::vector<string16>::const_iterator iter = name_tokens.begin();
       iter != name_tokens.end(); ++iter) {
    // |*iter| is already lower-cased.
    if (StringToLowerASCII(word) == *iter)
      return true;
  }

  return false;
}

void NameInfo::SetFirst(const string16& first) {
  first_ = first;
  first_tokens_.clear();
  Tokenize(first, kNameSplitChars, &first_tokens_);
  for (std::vector<string16>::iterator iter = first_tokens_.begin();
       iter != first_tokens_.end(); ++iter) {
    *iter = StringToLowerASCII(*iter);
  }
}

void NameInfo::SetMiddle(const string16& middle) {
  middle_ = middle;
  middle_tokens_.clear();
  Tokenize(middle, kNameSplitChars, &middle_tokens_);
  for (std::vector<string16>::iterator iter = middle_tokens_.begin();
       iter != middle_tokens_.end(); ++iter) {
    *iter = StringToLowerASCII(*iter);
  }
}

void NameInfo::SetLast(const string16& last) {
  last_ = last;
  last_tokens_.clear();
  Tokenize(last, kNameSplitChars, &last_tokens_);
  for (std::vector<string16>::iterator iter = last_tokens_.begin();
       iter != last_tokens_.end(); ++iter) {
    *iter = StringToLowerASCII(*iter);
  }
}

void NameInfo::SetFullName(const string16& full) {
  std::vector<string16> full_name_tokens;
  Tokenize(full, ASCIIToUTF16(" "), &full_name_tokens);
  // Clear the names.
  SetFirst(string16());
  SetMiddle(string16());
  SetLast(string16());

  // There are four possibilities: empty; first name; first and last names;
  // first, middle (possibly multiple strings) and then the last name.
  if (full_name_tokens.size() > 0) {
    SetFirst(full_name_tokens[0]);
    if (full_name_tokens.size() > 1) {
      SetLast(full_name_tokens.back());
      if (full_name_tokens.size() > 2) {
        full_name_tokens.erase(full_name_tokens.begin());
        full_name_tokens.pop_back();
        SetMiddle(JoinString(full_name_tokens, ' '));
      }
    }
  }
}

EmailInfo::EmailInfo() {}

EmailInfo::EmailInfo(const EmailInfo& info) : FormGroup() {
  *this = info;
}

EmailInfo::~EmailInfo() {}

EmailInfo& EmailInfo::operator=(const EmailInfo& info) {
  if (this == &info)
    return *this;

  email_ = info.email_;
  return *this;
}

void EmailInfo::GetPossibleFieldTypes(const string16& text,
                                      FieldTypeSet* possible_types) const {
  DCHECK(possible_types);
  // TODO(isherman): Investigate case-insensitive comparison.
  if (email_ == text)
    possible_types->insert(EMAIL_ADDRESS);
}

void EmailInfo::GetAvailableFieldTypes(FieldTypeSet* available_types) const {
  DCHECK(available_types);
  if (!email_.empty())
    available_types->insert(EMAIL_ADDRESS);
}

string16 EmailInfo::GetInfo(AutofillFieldType type) const {
  if (type == EMAIL_ADDRESS)
    return email_;

  return string16();
}

void EmailInfo::SetInfo(AutofillFieldType type, const string16& value) {
  DCHECK_EQ(EMAIL_ADDRESS, type);
  email_ = value;
}

CompanyInfo::CompanyInfo() {}

CompanyInfo::CompanyInfo(const CompanyInfo& info) : FormGroup() {
  *this = info;
}

CompanyInfo::~CompanyInfo() {}

CompanyInfo& CompanyInfo::operator=(const CompanyInfo& info) {
  if (this == &info)
    return *this;

  company_name_ = info.company_name_;
  return *this;
}

void CompanyInfo::GetPossibleFieldTypes(const string16& text,
                                        FieldTypeSet* possible_types) const {
  DCHECK(possible_types);

  if (company_name_ == text)
    possible_types->insert(COMPANY_NAME);
}

void CompanyInfo::GetAvailableFieldTypes(FieldTypeSet* available_types) const {
  DCHECK(available_types);

  if (!company_name_.empty())
    available_types->insert(COMPANY_NAME);
}

string16 CompanyInfo::GetInfo(AutofillFieldType type) const {
  if (type == COMPANY_NAME)
    return company_name_;

  return string16();
}

void CompanyInfo::SetInfo(AutofillFieldType type, const string16& value) {
  DCHECK_EQ(COMPANY_NAME, type);
  company_name_ = value;
}
