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

#include "third_party/blink/renderer/modules/indexeddb/idb_key.h"

#include <algorithm>
#include <memory>

#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"

namespace blink {

namespace {

size_t CalculateIDBKeyArraySize(const IDBKey::KeyArray& keys) {
  size_t size(0);
  for (const auto& key : keys)
    size += key.get()->SizeEstimate();
  return size;
}

}  // namespace

IDBKey::IDBKey()
    : type_(mojom::IDBKeyType::Invalid), size_estimate_(kIDBKeyOverheadSize) {}

IDBKey::IDBKey(mojom::IDBKeyType type, double number)
    : type_(type),
      number_(number),
      size_estimate_(kIDBKeyOverheadSize + sizeof(number_)) {}

IDBKey::IDBKey(const String& value)
    : type_(mojom::IDBKeyType::String),
      string_(value),
      size_estimate_(kIDBKeyOverheadSize + (string_.length() * sizeof(UChar))) {
}

IDBKey::IDBKey(scoped_refptr<SharedBuffer> value)
    : type_(mojom::IDBKeyType::Binary),
      binary_(std::move(value)),
      size_estimate_(kIDBKeyOverheadSize + binary_.get()->size()) {}

IDBKey::IDBKey(KeyArray key_array)
    : type_(mojom::IDBKeyType::Array),
      array_(std::move(key_array)),
      size_estimate_(kIDBKeyOverheadSize + CalculateIDBKeyArraySize(array_)) {}

IDBKey::~IDBKey() = default;

bool IDBKey::IsValid() const {
  if (type_ == mojom::IDBKeyType::Invalid)
    return false;

  if (type_ == mojom::IDBKeyType::Array) {
    for (const auto& element : array_) {
      if (!element->IsValid())
        return false;
    }
  }

  return true;
}

// Safely compare numbers (signed/unsigned ints/floats/doubles).
template <typename T>
static int CompareNumbers(const T& a, const T& b) {
  if (a < b)
    return -1;
  if (b < a)
    return 1;
  return 0;
}

int IDBKey::Compare(const IDBKey* other) const {
  DCHECK(other);
  if (type_ != other->type_)
    return type_ > other->type_ ? -1 : 1;

  switch (type_) {
    case mojom::IDBKeyType::Array:
      for (wtf_size_t i = 0; i < array_.size() && i < other->array_.size();
           ++i) {
        if (int result = array_[i]->Compare(other->array_[i].get()))
          return result;
      }
      return CompareNumbers(array_.size(), other->array_.size());
    case mojom::IDBKeyType::Binary:
      if (int result =
              memcmp(binary_->Data(), other->binary_->Data(),
                     std::min(binary_->size(), other->binary_->size())))
        return result < 0 ? -1 : 1;
      return CompareNumbers(binary_->size(), other->binary_->size());
    case mojom::IDBKeyType::String:
      return CodePointCompare(string_, other->string_);
    case mojom::IDBKeyType::Date:
    case mojom::IDBKeyType::Number:
      return CompareNumbers(number_, other->number_);

    // These values cannot be compared to each other.
    case mojom::IDBKeyType::Invalid:
    case mojom::IDBKeyType::Null:
    case mojom::IDBKeyType::Min:
      NOTREACHED();
      return 0;
  }

  NOTREACHED();
  return 0;
}

bool IDBKey::IsLessThan(const IDBKey* other) const {
  DCHECK(other);
  return Compare(other) == -1;
}

bool IDBKey::IsEqual(const IDBKey* other) const {
  if (!other)
    return false;

  return !Compare(other);
}

// static
WebVector<WebIDBKey> IDBKey::ToMultiEntryArray(
    std::unique_ptr<IDBKey> array_key) {
  DCHECK_EQ(array_key->type_, mojom::IDBKeyType::Array);
  WebVector<WebIDBKey> result;
  result.reserve(array_key->array_.size());
  for (std::unique_ptr<IDBKey>& key : array_key->array_) {
    if (key->IsValid())
      result.emplace_back(std::move(key));
  }

  // Remove duplicates using std::sort/std::unique rather than a hashtable to
  // avoid the complexity of implementing DefaultHash<IDBKey>.
  std::sort(
      result.begin(), result.end(), [](const WebIDBKey& a, const WebIDBKey& b) {
        return static_cast<IDBKey*>(a)->IsLessThan(static_cast<IDBKey*>(b));
      });
  const auto end = std::unique(result.begin(), result.end());
  DCHECK_LE(static_cast<wtf_size_t>(end - result.begin()), result.size());
  result.resize(end - result.begin());

  return result;
}

}  // namespace blink
