/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_OBJECT_STORE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_OBJECT_STORE_H_

#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_idb_index_parameters.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_cursor.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_index.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_metadata.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"

namespace blink {

class DOMStringList;
class ExceptionState;

class MODULES_EXPORT IDBObjectStore final : public ScriptWrappable {
  DEFINE_WRAPPERTYPEINFO();

 public:
  IDBObjectStore(scoped_refptr<IDBObjectStoreMetadata>, IDBTransaction*);
  ~IDBObjectStore() override = default;

  void Trace(Visitor*) const override;

  const IDBObjectStoreMetadata& Metadata() const { return *metadata_; }
  const IDBKeyPath& IdbKeyPath() const { return Metadata().key_path; }

  // Per spec prose, keyPath attribute should return the same object each time
  // (if it is not just a primitive type). The IDL cannot use [SameObject]
  // because the key path may not be an 'object'. So use [CachedAttribute],
  // but never dirty the cache.
  bool IsKeyPathDirty() const { return false; }

  // Implement the IDBObjectStore IDL
  int64_t Id() const { return Metadata().id; }
  const String& name() const { return Metadata().name; }
  void setName(const String& name, ExceptionState&);
  ScriptValue keyPath(ScriptState*) const;
  DOMStringList* indexNames() const;
  IDBTransaction* transaction() const { return transaction_.Get(); }
  bool autoIncrement() const { return Metadata().auto_increment; }

  IDBRequest* openCursor(ScriptState*,
                         const ScriptValue& range,
                         const String& direction,
                         ExceptionState&);
  IDBRequest* openKeyCursor(ScriptState*,
                            const ScriptValue& range,
                            const String& direction,
                            ExceptionState&);
  IDBRequest* get(ScriptState*, const ScriptValue& key, ExceptionState&);
  IDBRequest* getKey(ScriptState*, const ScriptValue& key, ExceptionState&);
  IDBRequest* getAll(ScriptState*,
                     const ScriptValue& range,
                     uint32_t max_count,
                     ExceptionState&);
  IDBRequest* getAll(ScriptState*, const ScriptValue& range, ExceptionState&);
  IDBRequest* getAllKeys(ScriptState*,
                         const ScriptValue& range,
                         uint32_t max_count,
                         ExceptionState&);
  IDBRequest* getAllKeys(ScriptState*,
                         const ScriptValue& range,
                         ExceptionState&);
  IDBRequest* add(ScriptState*, const ScriptValue& value, ExceptionState&);
  IDBRequest* add(ScriptState*,
                  const ScriptValue& value,
                  const ScriptValue& key,
                  ExceptionState&);
  IDBRequest* put(ScriptState*, const ScriptValue& value, ExceptionState&);
  IDBRequest* putAllValues(ScriptState*,
                           const HeapVector<ScriptValue>& values,
                           ExceptionState&);
  IDBRequest* DoPutAll(ScriptState* script_state,
                       const HeapVector<ScriptValue>& values,
                       const HeapVector<ScriptValue>& key_values,
                       ExceptionState& exception_state);
  IDBRequest* put(ScriptState*,
                  const ScriptValue& value,
                  const ScriptValue& key,
                  ExceptionState&);
  IDBRequest* Delete(ScriptState*, const ScriptValue& key, ExceptionState&);
  IDBRequest* clear(ScriptState*, ExceptionState&);

  IDBIndex* createIndex(ScriptState* script_state,
                        const String& name,
                        const StringOrStringSequence& key_path,
                        const IDBIndexParameters* options,
                        ExceptionState& exception_state) {
    return createIndex(script_state, name, IDBKeyPath(key_path), options,
                       exception_state);
  }
  IDBIndex* index(const String& name, ExceptionState&);
  void deleteIndex(const String& name, ExceptionState&);

  IDBRequest* count(ScriptState*, const ScriptValue& range, ExceptionState&);

  // Exposed for the use of IDBCursor::update().
  IDBRequest* DoPut(ScriptState*,
                    mojom::IDBPutMode,
                    const IDBRequest::Source&,
                    const ScriptValue&,
                    const IDBKey*,
                    ExceptionState&);

  // Used internally and by InspectorIndexedDBAgent:
  IDBRequest* openCursor(
      ScriptState*,
      IDBKeyRange*,
      mojom::IDBCursorDirection,
      mojom::IDBTaskType = mojom::IDBTaskType::Normal,
      IDBRequest::AsyncTraceState = IDBRequest::AsyncTraceState());
  IDBRequest* deleteFunction(
      ScriptState*,
      IDBKeyRange*,
      IDBRequest::AsyncTraceState = IDBRequest::AsyncTraceState());
  IDBRequest* getKeyGeneratorCurrentNumber(
      ScriptState*,
      IDBRequest::AsyncTraceState = IDBRequest::AsyncTraceState());

  void MarkDeleted();
  bool IsDeleted() const { return deleted_; }

  // True if this object store was created in its associated transaction.
  // Only valid if the store's associated transaction is a versionchange.
  bool IsNewlyCreated() const {
    DCHECK(transaction_->IsVersionChange());
    // Object store IDs are allocated sequentially, so we can tell if an object
    // store was created in this transaction by comparing its ID against the
    // database's maximum object store ID at the time when the transaction was
    // started.
    return Id() > transaction_->OldMaxObjectStoreId();
  }

  // Clears the cache used to implement the index() method.
  //
  // This should be called when the store's transaction clears its reference
  // to this IDBObjectStore instance, so the store can clear its references to
  // IDBIndex instances. This way, Oilpan can garbage-collect the instances
  // that are not referenced in JavaScript.
  //
  // For most stores, the condition above is met when the transaction
  // finishes. The exception is stores that are created and deleted in the
  // same transaction. Those stores will remain marked for deletion even if
  // the transaction aborts, so the transaction can forget about them (and
  // clear their index caches) right when they are deleted.
  void ClearIndexCache();

  // Sets the object store's metadata to a previous version.
  //
  // The reverting process includes reverting the metadata for the IDBIndex
  // instances that are still tracked by the store. It does not revert the
  // IDBIndex metadata for indexes that were deleted in this transaction.
  //
  // Used when a versionchange transaction is aborted.
  void RevertMetadata(scoped_refptr<IDBObjectStoreMetadata> previous_metadata);
  // This relies on the changes made by RevertMetadata().
  void RevertDeletedIndexMetadata(IDBIndex& deleted_index);

  // Used by IDBIndex::setName:
  bool ContainsIndex(const String& name) const {
    return FindIndexId(name) != IDBIndexMetadata::kInvalidId;
  }
  void RenameIndex(int64_t index_id, const String& new_name);

  WebIDBDatabase* BackendDB() const;

 private:
  using IDBIndexMap = HeapHashMap<String, Member<IDBIndex>>;

  IDBIndex* createIndex(ScriptState*,
                        const String& name,
                        const IDBKeyPath&,
                        const IDBIndexParameters*,
                        ExceptionState&);
  IDBRequest* DoPut(ScriptState*,
                    mojom::IDBPutMode,
                    const ScriptValue&,
                    const ScriptValue& key_value,
                    ExceptionState&);

  int64_t FindIndexId(const String& name) const;

  // The IDBObjectStoreMetadata is shared with the object store map in the
  // database's metadata.
  scoped_refptr<IDBObjectStoreMetadata> metadata_;
  Member<IDBTransaction> transaction_;
  bool deleted_ = false;

  // Caches the IDBIndex instances returned by the index() method.
  //
  // The spec requires that an object store's index() returns the same
  // IDBIndex instance for a specific index, so this cache is necessary
  // for correctness.
  //
  // index() throws for completed/aborted transactions, so this is not used
  // after a transaction is finished, and can be cleared.
  IDBIndexMap index_map_;

#if DCHECK_IS_ON()
  bool clear_index_cache_called_ = false;
#endif  // DCHECK_IS_ON()
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_OBJECT_STORE_H_
