/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 "types/CharType.hpp"

#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <utility>

#include "types/NullCoercibilityCheckMacro.hpp"
#include "types/Type.pb.h"
#include "types/TypeID.hpp"
#include "types/TypedValue.hpp"
#include "types/port/strnlen.hpp"
#include "utility/PtrMap.hpp"

#include "glog/logging.h"

using std::pair;
using std::size_t;
using std::strcmp;
using std::string;

namespace quickstep {

template <bool nullable_internal>
const CharType& CharType::InstanceInternal(const std::size_t length) {
  static PtrMap<size_t, CharType> instance_map;
  PtrMap<size_t, CharType>::iterator imit = instance_map.find(length);
  if (imit == instance_map.end()) {
    imit = instance_map.insert(length, new CharType(length, nullable_internal)).first;
  }
  return *(imit->second);
}

const CharType& CharType::InstanceNonNullable(const std::size_t length) {
  return InstanceInternal<false>(length);
}

const CharType& CharType::InstanceNullable(const std::size_t length) {
  return InstanceInternal<true>(length);
}

const CharType& CharType::InstanceFromProto(const serialization::Type &proto) {
  return Instance(proto.GetExtension(serialization::CharType::length), proto.nullable());
}

serialization::Type CharType::getProto() const {
  serialization::Type proto;
  proto.set_type_id(serialization::Type::CHAR);

  proto.set_nullable(nullable_);

  proto.SetExtension(serialization::CharType::length, length_);
  return proto;
}

bool CharType::isSafelyCoercibleFrom(const Type &original_type) const {
  QUICKSTEP_NULL_COERCIBILITY_CHECK();

  switch (original_type.getTypeID()) {
    case kChar:
      return original_type.maximumByteLength() <= length_;
    case kVarChar:
      return original_type.maximumByteLength() - 1 <= length_;
    default:
      return false;
  }
}

string CharType::getName() const {
  string name("Char(");
  name.append(std::to_string(length_));
  name.push_back(')');
  if (nullable_) {
    name.append(" NULL");
  }
  return name;
}

std::string CharType::printValueToString(const TypedValue &value) const {
  DCHECK(!value.isNull());

  const char *cstr = static_cast<const char*>(value.getOutOfLineData());
  return std::string(cstr, strnlen(cstr, length_));
}

void CharType::printValueToFile(const TypedValue &value,
                                FILE *file,
                                const int padding) const {
  DCHECK(!value.isNull());
  DCHECK_EQ(length_, static_cast<decltype(length_)>(static_cast<int>(length_)))
      << "Can not convert CHAR Type's maximum length " << length_
      << " to int for fprintf()";

  std::fprintf(file,
               "%*.*s",
               padding,
               static_cast<int>(length_),
               static_cast<const char*>(value.getOutOfLineData()));
}

bool CharType::parseValueFromString(const std::string &value_string,
                                    TypedValue *value) const {
  if (value_string.length() > length_) {
    return false;
  }

  *value = TypedValue(kChar,
                      value_string.c_str(),
                      value_string.length() == length_
                          ? value_string.length()
                          : value_string.length() + 1);
  value->ensureNotReference();
  return true;
}

TypedValue CharType::coerceValue(const TypedValue &original_value,
                                 const Type &original_type) const {
  DCHECK(isCoercibleFrom(original_type))
      << "Can't coerce value of Type " << original_type.getName()
      << " to Type " << getName();

  if (original_value.isNull()) {
    return makeNullValue();
  }

  const void *original_data = original_value.getOutOfLineData();
  const std::size_t original_data_size = original_value.getDataSize();

  // VARCHAR always has a null-terminator. CHAR(X) has a null-terminator when
  // string's length is less than X.
  const bool null_terminated
      = (original_type.getTypeID() == kVarChar)
        || (original_data_size < original_type.maximumByteLength())
        || (std::memchr(original_data, '\0', original_data_size) != nullptr);

  if (original_data_size <= length_) {
    if (null_terminated || (original_data_size == length_)) {
      TypedValue value_copy(original_value);
      value_copy.markType(kChar);
      return value_copy;
    } else {
      // Need to make a new NULL-terminated copy of the string.
      char *null_terminated_str = static_cast<char*>(std::malloc(original_data_size + 1));
      std::memcpy(null_terminated_str, original_data, original_data_size);
      null_terminated_str[original_data_size] = '\0';
      return TypedValue::CreateWithOwnedData(kChar,
                                             null_terminated_str,
                                             original_data_size + 1);
    }
  } else {
    // Need to truncate.
    if (original_value.ownsOutOfLineData()) {
      char *truncated_str = static_cast<char*>(std::malloc(length_));
      std::memcpy(truncated_str, original_data, length_);
      return TypedValue::CreateWithOwnedData(kChar, truncated_str, length_);
    } else {
      // Original is a reference, so we will just make a shorter reference.
      return TypedValue(kChar, original_data, length_);
    }
  }
}

}  // namespace quickstep
