/*
 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights
 * reserved.
 * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_FORM_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_FORM_CONTROLLER_H_

#include <memory>
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"

namespace blink {

class Document;
class FormKeyGenerator;
class HTMLFormElement;
class ListedElement;
class SavedFormState;

// FormControlState represents state of a single form control.
class FormControlState {
  DISALLOW_NEW();

 public:
  FormControlState() : type_(kTypeSkip) {}
  explicit FormControlState(const String& value) : type_(kTypeRestore) {
    values_.push_back(value);
  }
  CORE_EXPORT static FormControlState Deserialize(
      const Vector<String>& state_vector,
      wtf_size_t& index);
  FormControlState(const FormControlState& another) = default;
  FormControlState& operator=(const FormControlState&);

  bool IsFailure() const { return type_ == kTypeFailure; }
  wtf_size_t ValueSize() const { return values_.size(); }
  const String& operator[](wtf_size_t i) const { return values_[i]; }
  void Append(const String&);
  void SerializeTo(Vector<String>& state_vector) const;

 private:
  enum Type { kTypeSkip, kTypeRestore, kTypeFailure };
  explicit FormControlState(Type type) : type_(type) {}

  Type type_;
  Vector<String> values_;
};

inline FormControlState& FormControlState::operator=(
    const FormControlState& another) = default;

inline void FormControlState::Append(const String& value) {
  type_ = kTypeRestore;
  values_.push_back(value);
}

using SavedFormStateMap =
    HashMap<AtomicString, std::unique_ptr<SavedFormState>>;

class CORE_EXPORT DocumentState final : public GarbageCollected<DocumentState> {
 public:
  DocumentState(Document& document);
  void Trace(Visitor*) const;

  using ControlList = HeapVector<Member<ListedElement>, 64>;
  void InvalidateControlList();
  const ControlList& GetControlList();
  Vector<String> ToStateVector();

 private:
  Member<Document> document_;
  ControlList control_list_;
  bool is_control_list_dirty_ = true;
};

class CORE_EXPORT FormController final
    : public GarbageCollected<FormController> {
 public:
  FormController(Document& document);
  ~FormController();
  void Trace(Visitor*) const;

  void InvalidateStatefulFormControlList();
  // This should be called only by Document::FormElementsState().
  DocumentState* ControlStates() const;
  // This should be called only by Document::SetStateForNewFormElements().
  void SetStateForNewControls(const Vector<String>&);
  // Returns true if saved state is set to this object and there are entries
  // which are not consumed yet.
  bool HasControlStates() const;
  void WillDeleteForm(HTMLFormElement*);
  void RestoreControlStateFor(ListedElement&);
  void RestoreControlStateIn(HTMLFormElement&);
  // For a upgraded form-associated custom element.
  void RestoreControlStateOnUpgrade(ListedElement&);

  void ScheduleRestore();
  // Call RestoreAllControlsInDocumentOrder() if it is not called yet in order
  // to restore before 'pageshow' event.
  void RestoreImmediately();

  static Vector<String> GetReferencedFilePaths(
      const Vector<String>& state_vector);

 private:
  FormControlState TakeStateForControl(const ListedElement&);
  static void ControlStatesFromStateVector(const Vector<String>&,
                                           SavedFormStateMap&);
  // A helper for RestoreControlStateFor() and RestoreControlStateIn().
  void RestoreControlStateInternal(ListedElement& control);
  void RestoreAllControlsInDocumentOrder();

  Member<Document> document_;
  Member<DocumentState> document_state_;
  SavedFormStateMap saved_form_state_map_;
  Member<FormKeyGenerator> form_key_generator_;
  bool did_restore_all_ = false;
};

// Exposed for testing.
CORE_EXPORT String FormSignature(const HTMLFormElement& form);

}  // namespace blink
#endif
