// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0

#ifndef EIGEN_TENSOR_TENSOR_IO_H
#define EIGEN_TENSOR_TENSOR_IO_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

struct TensorIOFormat;

namespace internal {
template <typename Tensor, std::size_t rank, typename Format, typename EnableIf = void>
struct TensorPrinter;
}

template <typename Derived_>
struct TensorIOFormatBase {
  using Derived = Derived_;
  TensorIOFormatBase(const std::vector<std::string>& separator, const std::vector<std::string>& prefix,
                     const std::vector<std::string>& suffix, int precision = StreamPrecision, int flags = 0,
                     const std::string& tenPrefix = "", const std::string& tenSuffix = "", const char fill = ' ')
      : tenPrefix(tenPrefix),
        tenSuffix(tenSuffix),
        prefix(prefix),
        suffix(suffix),
        separator(separator),
        fill(fill),
        precision(precision),
        flags(flags) {
    init_spacer();
  }

  void init_spacer() {
    if (flags & DontAlignCols) return;
    spacer.resize(prefix.size());
    spacer[0] = "";
    int i = int(tenPrefix.length()) - 1;
    while (i >= 0 && tenPrefix[i] != '\n') {
      spacer[0] += ' ';
      i--;
    }

    for (std::size_t k = 1; k < prefix.size(); k++) {
      int j = int(prefix[k].length()) - 1;
      while (j >= 0 && prefix[k][j] != '\n') {
        spacer[k] += ' ';
        j--;
      }
    }
  }

  std::string tenPrefix;
  std::string tenSuffix;
  std::vector<std::string> prefix;
  std::vector<std::string> suffix;
  std::vector<std::string> separator;
  char fill;
  int precision;
  int flags;
  std::vector<std::string> spacer{};
};

struct TensorIOFormatNumpy : public TensorIOFormatBase<TensorIOFormatNumpy> {
  using Base = TensorIOFormatBase<TensorIOFormatNumpy>;
  TensorIOFormatNumpy()
      : Base(/*separator=*/{" ", "\n"}, /*prefix=*/{"", "["}, /*suffix=*/{"", "]"}, /*precision=*/StreamPrecision,
             /*flags=*/0, /*tenPrefix=*/"[", /*tenSuffix=*/"]") {}
};

struct TensorIOFormatNative : public TensorIOFormatBase<TensorIOFormatNative> {
  using Base = TensorIOFormatBase<TensorIOFormatNative>;
  TensorIOFormatNative()
      : Base(/*separator=*/{", ", ",\n", "\n"}, /*prefix=*/{"", "{"}, /*suffix=*/{"", "}"},
             /*precision=*/StreamPrecision, /*flags=*/0, /*tenPrefix=*/"{", /*tenSuffix=*/"}") {}
};

struct TensorIOFormatPlain : public TensorIOFormatBase<TensorIOFormatPlain> {
  using Base = TensorIOFormatBase<TensorIOFormatPlain>;
  TensorIOFormatPlain()
      : Base(/*separator=*/{" ", "\n", "\n", ""}, /*prefix=*/{""}, /*suffix=*/{""}, /*precision=*/StreamPrecision,
             /*flags=*/0, /*tenPrefix=*/"", /*tenSuffix=*/"") {}
};

struct TensorIOFormatLegacy : public TensorIOFormatBase<TensorIOFormatLegacy> {
  using Base = TensorIOFormatBase<TensorIOFormatLegacy>;
  TensorIOFormatLegacy()
      : Base(/*separator=*/{", ", "\n"}, /*prefix=*/{"", "["}, /*suffix=*/{"", "]"}, /*precision=*/StreamPrecision,
             /*flags=*/0, /*tenPrefix=*/"", /*tenSuffix=*/"") {}
};

struct TensorIOFormat : public TensorIOFormatBase<TensorIOFormat> {
  using Base = TensorIOFormatBase<TensorIOFormat>;
  TensorIOFormat(const std::vector<std::string>& separator, const std::vector<std::string>& prefix,
                 const std::vector<std::string>& suffix, int precision = StreamPrecision, int flags = 0,
                 const std::string& tenPrefix = "", const std::string& tenSuffix = "", const char fill = ' ')
      : Base(separator, prefix, suffix, precision, flags, tenPrefix, tenSuffix, fill) {}

  static inline const TensorIOFormatNumpy Numpy() { return TensorIOFormatNumpy{}; }

  static inline const TensorIOFormatPlain Plain() { return TensorIOFormatPlain{}; }

  static inline const TensorIOFormatNative Native() { return TensorIOFormatNative{}; }

  static inline const TensorIOFormatLegacy Legacy() { return TensorIOFormatLegacy{}; }
};

template <typename T, int Layout, int rank, typename Format>
class TensorWithFormat;
// specialize for Layout=ColMajor, Layout=RowMajor and rank=0.
template <typename T, int rank, typename Format>
class TensorWithFormat<T, RowMajor, rank, Format> {
 public:
  TensorWithFormat(const T& tensor, const Format& format) : t_tensor(tensor), t_format(format) {}

  friend std::ostream& operator<<(std::ostream& os, const TensorWithFormat<T, RowMajor, rank, Format>& wf) {
    // Evaluate the expression if needed
    typedef TensorEvaluator<const TensorForcedEvalOp<const T>, DefaultDevice> Evaluator;
    TensorForcedEvalOp<const T> eval = wf.t_tensor.eval();
    Evaluator tensor(eval, DefaultDevice());
    tensor.evalSubExprsIfNeeded(nullptr);
    internal::TensorPrinter<Evaluator, rank, Format>::run(os, tensor, wf.t_format);
    // Cleanup.
    tensor.cleanup();
    return os;
  }

 protected:
  T t_tensor;
  Format t_format;
};

template <typename T, int rank, typename Format>
class TensorWithFormat<T, ColMajor, rank, Format> {
 public:
  TensorWithFormat(const T& tensor, const Format& format) : t_tensor(tensor), t_format(format) {}

  friend std::ostream& operator<<(std::ostream& os, const TensorWithFormat<T, ColMajor, rank, Format>& wf) {
    // Switch to RowMajor storage and print afterwards
    typedef typename T::Index IndexType;
    std::array<IndexType, rank> shuffle;
    std::array<IndexType, rank> id;
    std::iota(id.begin(), id.end(), IndexType(0));
    std::copy(id.begin(), id.end(), shuffle.rbegin());
    auto tensor_row_major = wf.t_tensor.swap_layout().shuffle(shuffle);

    // Evaluate the expression if needed
    typedef TensorEvaluator<const TensorForcedEvalOp<const decltype(tensor_row_major)>, DefaultDevice> Evaluator;
    TensorForcedEvalOp<const decltype(tensor_row_major)> eval = tensor_row_major.eval();
    Evaluator tensor(eval, DefaultDevice());
    tensor.evalSubExprsIfNeeded(nullptr);
    internal::TensorPrinter<Evaluator, rank, Format>::run(os, tensor, wf.t_format);
    // Cleanup.
    tensor.cleanup();
    return os;
  }

 protected:
  T t_tensor;
  Format t_format;
};

template <typename T, typename Format>
class TensorWithFormat<T, ColMajor, 0, Format> {
 public:
  TensorWithFormat(const T& tensor, const Format& format) : t_tensor(tensor), t_format(format) {}

  friend std::ostream& operator<<(std::ostream& os, const TensorWithFormat<T, ColMajor, 0, Format>& wf) {
    // Evaluate the expression if needed
    typedef TensorEvaluator<const TensorForcedEvalOp<const T>, DefaultDevice> Evaluator;
    TensorForcedEvalOp<const T> eval = wf.t_tensor.eval();
    Evaluator tensor(eval, DefaultDevice());
    tensor.evalSubExprsIfNeeded(nullptr);
    internal::TensorPrinter<Evaluator, 0, Format>::run(os, tensor, wf.t_format);
    // Cleanup.
    tensor.cleanup();
    return os;
  }

 protected:
  T t_tensor;
  Format t_format;
};

namespace internal {

// Default scalar printer.
template <typename Scalar, typename Format, typename EnableIf = void>
struct ScalarPrinter {
  static void run(std::ostream& stream, const Scalar& scalar, const Format&) { stream << scalar; }
};

template <typename Scalar>
struct ScalarPrinter<Scalar, TensorIOFormatNumpy, std::enable_if_t<NumTraits<Scalar>::IsComplex>> {
  static void run(std::ostream& stream, const Scalar& scalar, const TensorIOFormatNumpy&) {
    stream << numext::real(scalar) << "+" << numext::imag(scalar) << "j";
  }
};

template <typename Scalar>
struct ScalarPrinter<Scalar, TensorIOFormatNative, std::enable_if_t<NumTraits<Scalar>::IsComplex>> {
  static void run(std::ostream& stream, const Scalar& scalar, const TensorIOFormatNative&) {
    stream << "{" << numext::real(scalar) << ", " << numext::imag(scalar) << "}";
  }
};

template <typename Tensor, std::size_t rank, typename Format, typename EnableIf>
struct TensorPrinter {
  using Scalar = std::remove_const_t<typename Tensor::Scalar>;

  static void run(std::ostream& s, const Tensor& tensor, const Format& fmt) {
    typedef typename Tensor::Index IndexType;

    eigen_assert(Tensor::Layout == RowMajor);
    typedef std::conditional_t<std::is_same<Scalar, char>::value || std::is_same<Scalar, unsigned char>::value ||
                                   std::is_same<Scalar, numext::int8_t>::value ||
                                   std::is_same<Scalar, numext::uint8_t>::value,
                               int,
                               std::conditional_t<std::is_same<Scalar, std::complex<char>>::value ||
                                                      std::is_same<Scalar, std::complex<unsigned char>>::value ||
                                                      std::is_same<Scalar, std::complex<numext::int8_t>>::value ||
                                                      std::is_same<Scalar, std::complex<numext::uint8_t>>::value,
                                                  std::complex<int>, const Scalar&>>
        PrintType;
    using PrintScalar = std::remove_const_t<std::remove_reference_t<PrintType>>;

    const IndexType total_size = array_prod(tensor.dimensions());

    std::streamsize explicit_precision;
    if (fmt.precision == StreamPrecision) {
      explicit_precision = 0;
    } else if (fmt.precision == FullPrecision) {
      EIGEN_IF_CONSTEXPR (NumTraits<Scalar>::IsInteger) {
        explicit_precision = 0;
      } else {
        explicit_precision = significant_decimals_impl<Scalar>::run();
      }
    } else {
      explicit_precision = fmt.precision;
    }

    std::streamsize old_precision = 0;
    if (explicit_precision) old_precision = s.precision(explicit_precision);

    IndexType width = 0;
    bool align_cols = !(fmt.flags & DontAlignCols);
    if (align_cols) {
      // compute the largest width
      for (IndexType i = 0; i < total_size; i++) {
        std::stringstream sstr;
        sstr.copyfmt(s);
        ScalarPrinter<PrintScalar, Format>::run(sstr, static_cast<PrintType>(tensor.data()[i]), fmt);
        width = std::max<IndexType>(width, IndexType(sstr.str().length()));
      }
    }
    s << fmt.tenPrefix;
    for (IndexType i = 0; i < total_size; i++) {
      std::array<bool, rank> is_at_end{};
      std::array<bool, rank> is_at_begin{};

      // is the ith element the end of a coeff (always true), of a row, of a matrix, ...?
      for (std::size_t k = 0; k < rank; k++) {
        if ((i + 1) % (std::accumulate(tensor.dimensions().rbegin(), tensor.dimensions().rbegin() + k, 1,
                                       std::multiplies<IndexType>())) ==
            0) {
          is_at_end[k] = true;
        }
      }

      // is the ith element the begin of a coeff (always true), of a row, of a matrix, ...?
      for (std::size_t k = 0; k < rank; k++) {
        if (i % (std::accumulate(tensor.dimensions().rbegin(), tensor.dimensions().rbegin() + k, 1,
                                 std::multiplies<IndexType>())) ==
            0) {
          is_at_begin[k] = true;
        }
      }

      // do we have a line break?
      bool is_at_begin_after_newline = false;
      for (std::size_t k = 0; k < rank; k++) {
        if (is_at_begin[k]) {
          std::size_t separator_index = (k < fmt.separator.size()) ? k : fmt.separator.size() - 1;
          if (fmt.separator[separator_index].find('\n') != std::string::npos) {
            is_at_begin_after_newline = true;
          }
        }
      }

      bool is_at_end_before_newline = false;
      for (std::size_t k = 0; k < rank; k++) {
        if (is_at_end[k]) {
          std::size_t separator_index = (k < fmt.separator.size()) ? k : fmt.separator.size() - 1;
          if (fmt.separator[separator_index].find('\n') != std::string::npos) {
            is_at_end_before_newline = true;
          }
        }
      }

      std::stringstream suffix, prefix, separator;
      for (std::size_t k = 0; k < rank; k++) {
        std::size_t suffix_index = (k < fmt.suffix.size()) ? k : fmt.suffix.size() - 1;
        if (is_at_end[k]) {
          suffix << fmt.suffix[suffix_index];
        }
      }
      for (std::size_t k = 0; k < rank; k++) {
        std::size_t separator_index = (k < fmt.separator.size()) ? k : fmt.separator.size() - 1;
        if (is_at_end[k] &&
            (!is_at_end_before_newline || fmt.separator[separator_index].find('\n') != std::string::npos)) {
          separator << fmt.separator[separator_index];
        }
      }
      for (std::size_t k = 0; k < rank; k++) {
        std::size_t spacer_index = (k < fmt.spacer.size()) ? k : fmt.spacer.size() - 1;
        if (i != 0 && is_at_begin_after_newline && (!is_at_begin[k] || k == 0)) {
          prefix << fmt.spacer[spacer_index];
        }
      }
      for (int k = rank - 1; k >= 0; k--) {
        std::size_t prefix_index = (static_cast<std::size_t>(k) < fmt.prefix.size()) ? k : fmt.prefix.size() - 1;
        if (is_at_begin[k]) {
          prefix << fmt.prefix[prefix_index];
        }
      }

      s << prefix.str();
      // So we don't mess around with formatting, output scalar to a string stream, and adjust the width/fill manually.
      std::stringstream sstr;
      sstr.copyfmt(s);
      ScalarPrinter<PrintScalar, Format>::run(sstr, static_cast<PrintType>(tensor.data()[i]), fmt);
      std::string scalar_str = sstr.str();
      IndexType scalar_width = scalar_str.length();
      if (width && scalar_width < width) {
        std::string filler;
        for (IndexType j = scalar_width; j < width; ++j) {
          filler.push_back(fmt.fill);
        }
        s << filler;
      }
      s << scalar_str;
      s << suffix.str();
      if (i < total_size - 1) {
        s << separator.str();
      }
    }
    s << fmt.tenSuffix;
    if (explicit_precision) s.precision(old_precision);
  }
};

template <typename Tensor, std::size_t rank>
struct TensorPrinter<Tensor, rank, TensorIOFormatLegacy, std::enable_if_t<rank != 0>> {
  using Format = TensorIOFormatLegacy;
  using Scalar = std::remove_const_t<typename Tensor::Scalar>;

  static void run(std::ostream& s, const Tensor& tensor, const Format&) {
    typedef typename Tensor::Index IndexType;
    // backwards compatibility case: print tensor after reshaping to matrix of size dim(0) x
    // (dim(1)*dim(2)*...*dim(rank-1)).
    const IndexType total_size = internal::array_prod(tensor.dimensions());
    if (total_size > 0) {
      const IndexType first_dim = Eigen::internal::array_get<0>(tensor.dimensions());
      Map<const Array<Scalar, Dynamic, Dynamic, Tensor::Layout>> matrix(tensor.data(), first_dim,
                                                                        total_size / first_dim);
      s << matrix;
      return;
    }
  }
};

template <typename Tensor, typename Format>
struct TensorPrinter<Tensor, 0, Format> {
  static void run(std::ostream& s, const Tensor& tensor, const Format& fmt) {
    using Scalar = std::remove_const_t<typename Tensor::Scalar>;

    std::streamsize explicit_precision;
    if (fmt.precision == StreamPrecision) {
      explicit_precision = 0;
    } else if (fmt.precision == FullPrecision) {
      EIGEN_IF_CONSTEXPR (NumTraits<Scalar>::IsInteger) {
        explicit_precision = 0;
      } else {
        explicit_precision = significant_decimals_impl<Scalar>::run();
      }
    } else {
      explicit_precision = fmt.precision;
    }

    std::streamsize old_precision = 0;
    if (explicit_precision) old_precision = s.precision(explicit_precision);
    s << fmt.tenPrefix;
    ScalarPrinter<Scalar, Format>::run(s, tensor.coeff(0), fmt);
    s << fmt.tenSuffix;
    if (explicit_precision) s.precision(old_precision);
  }
};

}  // end namespace internal
template <typename T>
std::ostream& operator<<(std::ostream& s, const TensorBase<T, ReadOnlyAccessors>& t) {
  s << t.format(TensorIOFormat::Plain());
  return s;
}
}  // end namespace Eigen

#endif  // EIGEN_TENSOR_TENSOR_IO_H
