// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "media/base/color_space.h"

#include "starboard/memory.h"

namespace gfx {

ColorSpace::PrimaryID ColorSpace::PrimaryIDFromInt(int primary_id) {
  if (primary_id < 0 || primary_id > static_cast<int>(kPrimaryIdLast))
    return kPrimaryIdUnknown;
  if (primary_id > static_cast<int>(kPrimaryIdLastStandardValue) &&
      primary_id < 1000)
    return kPrimaryIdUnknown;
  return static_cast<PrimaryID>(primary_id);
}

ColorSpace::TransferID ColorSpace::TransferIDFromInt(int transfer_id) {
  if (transfer_id < 0 || transfer_id > static_cast<int>(kTransferIdLast))
    return kTransferIdUnknown;
  if (transfer_id > static_cast<int>(kTransferIdLastStandardValue) &&
      transfer_id < 1000)
    return kTransferIdUnknown;
  return static_cast<TransferID>(transfer_id);
}

ColorSpace::MatrixID ColorSpace::MatrixIDFromInt(int matrix_id) {
  if (matrix_id < 0 || matrix_id > static_cast<int>(kMatrixIdLast))
    return kMatrixIdUnknown;
  if (matrix_id > static_cast<int>(kMatrixIdLastStandardValue) &&
      matrix_id < 1000)
    return kMatrixIdUnknown;
  return static_cast<MatrixID>(matrix_id);
}

ColorSpace::ColorSpace()
    : primaries_(kPrimaryIdUnspecified),
      transfer_(kTransferIdUnspecified),
      matrix_(kMatrixIdUnspecified),
      range_(kRangeIdLimited) {
  SbMemorySet(custom_primary_matrix_, 0, sizeof(custom_primary_matrix_));
}

ColorSpace::ColorSpace(PrimaryID primaries,
                       TransferID transfer,
                       MatrixID matrix,
                       RangeID range)
    : primaries_(primaries),
      transfer_(transfer),
      matrix_(matrix),
      range_(range) {
  SbMemorySet(custom_primary_matrix_, 0, sizeof(custom_primary_matrix_));
}

ColorSpace::ColorSpace(int primaries, int transfer, int matrix, RangeID range)
    : primaries_(PrimaryIDFromInt(primaries)),
      transfer_(TransferIDFromInt(transfer)),
      matrix_(MatrixIDFromInt(matrix)),
      range_(range) {
  SbMemorySet(custom_primary_matrix_, 0, sizeof(custom_primary_matrix_));
}

ColorSpace::ColorSpace(const ColorSpace& other)
    : primaries_(other.primaries_),
      transfer_(other.transfer_),
      matrix_(other.matrix_),
      range_(other.range_) {
  SbMemoryCopy(custom_primary_matrix_, other.custom_primary_matrix_,
               sizeof(custom_primary_matrix_));
}

ColorSpace::~ColorSpace() {}

// Static
ColorSpace ColorSpace::CreateXYZD50() {
  return ColorSpace(kPrimaryIdXyzD50, kTransferIdLinear, kMatrixIdRgb,
                    kRangeIdFull);
}

// static
ColorSpace ColorSpace::CreateJpeg() {
  return ColorSpace(kPrimaryIdBt709, kTransferIdIec6196621, kMatrixIdBt709,
                    kRangeIdFull);
}

// static
ColorSpace ColorSpace::CreateREC601() {
  return ColorSpace(kPrimaryIdSmpte170M, kTransferIdSmpte170M,
                    kMatrixIdSmpte170M, kRangeIdLimited);
}

// static
ColorSpace ColorSpace::CreateREC709() {
  return ColorSpace(kPrimaryIdBt709, kTransferIdBt709, kMatrixIdBt709,
                    kRangeIdLimited);
}

bool ColorSpace::operator==(const ColorSpace& other) const {
  if (primaries_ != other.primaries_ || transfer_ != other.transfer_ ||
      matrix_ != other.matrix_ || range_ != other.range_)
    return false;
  if (primaries_ == kPrimaryIdCustom &&
      SbMemoryCompare(custom_primary_matrix_, other.custom_primary_matrix_,
                      sizeof(custom_primary_matrix_)))
    return false;
  return true;
}

bool ColorSpace::operator!=(const ColorSpace& other) const {
  return !(*this == other);
}

bool ColorSpace::operator<(const ColorSpace& other) const {
  if (primaries_ < other.primaries_)
    return true;
  if (primaries_ > other.primaries_)
    return false;
  if (transfer_ < other.transfer_)
    return true;
  if (transfer_ > other.transfer_)
    return false;
  if (matrix_ < other.matrix_)
    return true;
  if (matrix_ > other.matrix_)
    return false;
  if (range_ < other.range_)
    return true;
  if (range_ > other.range_)
    return false;
  if (primaries_ == kPrimaryIdCustom) {
    int primary_result =
        SbMemoryCompare(custom_primary_matrix_, other.custom_primary_matrix_,
                        sizeof(custom_primary_matrix_));
    if (primary_result < 0)
      return true;
    if (primary_result > 0)
      return false;
  }
  return false;
}

}  // namespace gfx
