/**
 * 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.
 */
#ifndef IOTDB_COMMON_H
#define IOTDB_COMMON_H

#include <cstdint>
#include <ctime>
#include <exception>
#include <map>
#include <string>
#include <vector>

#include "Date.h"
#include "Endpoint.h"
#include "Export.h"
#include "Optional.h"
#include "Status.h"

std::string getTimePrecision(int32_t timeFactor);

std::string formatDatetime(const std::string &format,
                           const std::string &precision, int64_t timestamp,
                           const std::string &zoneId);

std::tm convertToTimestamp(int64_t value, int32_t timeFactor);
std::tm int32ToDate(int32_t value);

namespace Version {
enum Version { V_0_12, V_0_13, V_1_0 };
}

namespace CompressionType {
enum CompressionType {
  UNCOMPRESSED = (char)0,
  SNAPPY = (char)1,
  GZIP = (char)2,
  LZO = (char)3,
  SDT = (char)4,
  PAA = (char)5,
  PLA = (char)6,
  LZ4 = (char)7,
  ZSTD = (char)8,
  LZMA2 = (char)9,
};
}

namespace TSDataType {
enum TSDataType {
  BOOLEAN = (char)0,
  INT32 = (char)1,
  INT64 = (char)2,
  FLOAT = (char)3,
  DOUBLE = (char)4,
  TEXT = (char)5,
  VECTOR = (char)6,
  UNKNOWN = (char)7,
  TIMESTAMP = (char)8,
  DATE = (char)9,
  BLOB = (char)10,
  STRING = (char)11,
  OBJECT = (char)12
};
}

TSDataType::TSDataType getDataTypeByStr(const std::string &typeStr);

namespace TSEncoding {
enum TSEncoding {
  PLAIN = (char)0,
  DICTIONARY = (char)1,
  RLE = (char)2,
  DIFF = (char)3,
  TS_2DIFF = (char)4,
  BITMAP = (char)5,
  GORILLA_V1 = (char)6,
  REGULAR = (char)7,
  GORILLA = (char)8,
  ZIGZAG = (char)9,
  FREQ = (char)10,
  INVALID_ENCODING = (char)255
};
}

namespace TSStatusCode {
enum TSStatusCode {
  SUCCESS_STATUS = 200,

  INCOMPATIBLE_VERSION = 201,
  CONFIGURATION_ERROR = 202,
  START_UP_ERROR = 203,
  SHUT_DOWN_ERROR = 204,

  UNSUPPORTED_OPERATION = 300,
  EXECUTE_STATEMENT_ERROR = 301,
  MULTIPLE_ERROR = 302,
  ILLEGAL_PARAMETER = 303,
  OVERLAP_WITH_EXISTING_TASK = 304,
  INTERNAL_SERVER_ERROR = 305,

  REDIRECTION_RECOMMEND = 400,

  DATABASE_NOT_EXIST = 500,
  DATABASE_ALREADY_EXISTS = 501,
  SERIES_OVERFLOW = 502,
  TIMESERIES_ALREADY_EXIST = 503,
  TIMESERIES_IN_BLACK_LIST = 504,
  ALIAS_ALREADY_EXIST = 505,
  PATH_ALREADY_EXIST = 506,
  METADATA_ERROR = 507,
  PATH_NOT_EXIST = 508,
  ILLEGAL_PATH = 509,
  CREATE_TEMPLATE_ERROR = 510,
  DUPLICATED_TEMPLATE = 511,
  UNDEFINED_TEMPLATE = 512,
  TEMPLATE_NOT_SET = 513,
  DIFFERENT_TEMPLATE = 514,
  TEMPLATE_IS_IN_USE = 515,
  TEMPLATE_INCOMPATIBLE = 516,
  SEGMENT_NOT_FOUND = 517,
  PAGE_OUT_OF_SPACE = 518,
  RECORD_DUPLICATED = 519,
  SEGMENT_OUT_OF_SPACE = 520,
  PBTREE_FILE_NOT_EXISTS = 521,
  OVERSIZE_RECORD = 522,
  PBTREE_FILE_REDO_LOG_BROKEN = 523,
  TEMPLATE_NOT_ACTIVATED = 524,

  SYSTEM_READ_ONLY = 600,
  STORAGE_ENGINE_ERROR = 601,
  STORAGE_ENGINE_NOT_READY = 602,

  PLAN_FAILED_NETWORK_PARTITION = 721
};
}

class Field {
public:
  TSDataType::TSDataType dataType = TSDataType::UNKNOWN;
  Optional<bool> boolV;
  Optional<int> intV;
  Optional<IoTDBDate> dateV;
  Optional<int64_t> longV;
  Optional<float> floatV;
  Optional<double> doubleV;
  Optional<std::string> stringV;

  explicit Field(TSDataType::TSDataType a) { dataType = a; }

  Field() = default;

  bool isNull() const {
    switch (dataType) {
    case TSDataType::BOOLEAN:
      return !boolV.is_initialized();
    case TSDataType::INT32:
      return !intV.is_initialized();
    case TSDataType::INT64:
    case TSDataType::TIMESTAMP:
      return !longV.is_initialized();
    case TSDataType::FLOAT:
      return !floatV.is_initialized();
    case TSDataType::DOUBLE:
      return !doubleV.is_initialized();
    case TSDataType::TEXT:
    case TSDataType::STRING:
    case TSDataType::BLOB:
      return !stringV.is_initialized();
    case TSDataType::DATE:
      return !dateV.is_initialized();
    default:
      return true;
    }
  }
};

enum class ColumnCategory { TAG, FIELD, ATTRIBUTE };

class MyStringBuffer {
public:
  MyStringBuffer();
  explicit MyStringBuffer(const std::string &str);

  void reserve(size_t n);
  void clear();
  bool hasRemaining();
  int getInt();
  IoTDBDate getDate();
  int64_t getInt64();
  float getFloat();
  double getDouble();
  char getChar();
  bool getBool();
  std::string getString();

  void putInt(int ins);
  void putDate(IoTDBDate date);
  void putInt64(int64_t ins);
  void putFloat(float ins);
  void putDouble(double ins);
  void putChar(char ins);
  void putBool(bool ins);
  void putString(const std::string &ins);
  void concat(const std::string &ins);

public:
  std::string str;
  size_t pos;

private:
  void checkBigEndian();
  const char *getOrderedByte(size_t len);
  void putOrderedByte(char *buf, int len);

private:
  bool isBigEndian{};
  char numericBuf[8]{};
};

class BitMap {
public:
  explicit BitMap(size_t size = 0);
  void resize(size_t size);
  bool mark(size_t position);
  bool unmark(size_t position);
  void markAll();
  void reset();
  bool isMarked(size_t position) const;
  bool isAllUnmarked() const;
  bool isAllMarked() const;
  const std::vector<char> &getByteArray() const;
  size_t getSize() const;

private:
  size_t size;
  std::vector<char> bits;
};

class IoTDBException : public std::exception {
public:
  IoTDBException() = default;

  explicit IoTDBException(const std::string &m) : message(m) {}

  explicit IoTDBException(const char *m) : message(m) {}

  virtual const char *what() const noexcept override { return message.c_str(); }

private:
  std::string message;
};

std::string extractExceptionMessage(const std::exception &exception);
std::string extractExceptionMessage(const std::exception_ptr &exceptionPtr);

class DateTimeParseException : public IoTDBException {
private:
  std::string parsedString;
  int errorIndex;

public:
  explicit DateTimeParseException(const std::string &message,
                                  std::string parsedData, int errorIndex)
      : IoTDBException(message), parsedString(std::move(parsedData)),
        errorIndex(errorIndex) {}

  explicit DateTimeParseException(const std::string &message,
                                  std::string parsedData, int errorIndex,
                                  const std::exception &cause)
      : IoTDBException(message + " [Caused by: " + cause.what() + "]"),
        parsedString(std::move(parsedData)), errorIndex(errorIndex) {}

  const std::string &getParsedString() const noexcept { return parsedString; }

  int getErrorIndex() const noexcept { return errorIndex; }

  const char *what() const noexcept override {
    static std::string fullMsg;
    fullMsg = std::string(IoTDBException::what()) +
              "\nParsed data: " + parsedString +
              "\nError index: " + std::to_string(errorIndex);
    return fullMsg.c_str();
  }
};

class IoTDBConnectionException : public IoTDBException {
public:
  IoTDBConnectionException() {}

  explicit IoTDBConnectionException(const char *m) : IoTDBException(m) {}

  explicit IoTDBConnectionException(const std::string &m) : IoTDBException(m) {}
};

class ExecutionException : public IoTDBException {
public:
  ExecutionException() {}

  explicit ExecutionException(const char *m) : IoTDBException(m) {}

  explicit ExecutionException(const std::string &m) : IoTDBException(m) {}

  explicit ExecutionException(const std::string &m, const Status &tsStatus)
      : IoTDBException(m), status(tsStatus) {}

  Status status;
};

class BatchExecutionException : public IoTDBException {
public:
  BatchExecutionException() {}

  explicit BatchExecutionException(const char *m) : IoTDBException(m) {}

  explicit BatchExecutionException(const std::string &m) : IoTDBException(m) {}

  explicit BatchExecutionException(const std::vector<Status> &statusList)
      : statusList(statusList) {}

  BatchExecutionException(const std::string &m,
                          const std::vector<Status> &statusList)
      : IoTDBException(m), statusList(statusList) {}

  std::vector<Status> statusList;
};

class RedirectException : public IoTDBException {
public:
  RedirectException() {}

  explicit RedirectException(const char *m) : IoTDBException(m) {}

  explicit RedirectException(const std::string &m) : IoTDBException(m) {}

  RedirectException(const std::string &m, const Endpoint &endPoint)
      : IoTDBException(m), endPoint(endPoint) {}

  RedirectException(const std::string &m,
                    const std::map<std::string, Endpoint> &deviceEndPointMap)
      : IoTDBException(m), deviceEndPointMap(deviceEndPointMap) {}

  RedirectException(const std::string &m,
                    const std::vector<Endpoint> &endPointList)
      : IoTDBException(m), endPointList(endPointList) {}

  Endpoint endPoint;
  std::map<std::string, Endpoint> deviceEndPointMap;
  std::vector<Endpoint> endPointList;
};

class UnSupportedDataTypeException : public IoTDBException {
public:
  UnSupportedDataTypeException() {}

  explicit UnSupportedDataTypeException(const char *m) : IoTDBException(m) {}

  explicit UnSupportedDataTypeException(const std::string &m)
      : IoTDBException("UnSupported dataType: " + m) {}
};

class SchemaNotFoundException : public IoTDBException {
public:
  SchemaNotFoundException() {}

  explicit SchemaNotFoundException(const char *m) : IoTDBException(m) {}

  explicit SchemaNotFoundException(const std::string &m) : IoTDBException(m) {}
};

class StatementExecutionException : public IoTDBException {
public:
  StatementExecutionException() {}

  explicit StatementExecutionException(const char *m) : IoTDBException(m) {}

  explicit StatementExecutionException(const std::string &m)
      : IoTDBException(m) {}
};

enum LogLevelType { LEVEL_DEBUG = 0, LEVEL_INFO, LEVEL_WARN, LEVEL_ERROR };

extern IOTDB_SESSION_API LogLevelType LOG_LEVEL;

#define log_debug(fmt, ...)                                                    \
  do {                                                                         \
    if (LOG_LEVEL <= LEVEL_DEBUG) {                                            \
      std::string s = std::string("[DEBUG] %s:%d (%s) - ") + fmt + "\n";       \
      printf(s.c_str(), __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);      \
    }                                                                          \
  } while (0)
#define log_info(fmt, ...)                                                     \
  do {                                                                         \
    if (LOG_LEVEL <= LEVEL_INFO) {                                             \
      std::string s = std::string("[INFO]  %s:%d (%s) - ") + fmt + "\n";       \
      printf(s.c_str(), __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);      \
    }                                                                          \
  } while (0)
#define log_warn(fmt, ...)                                                     \
  do {                                                                         \
    if (LOG_LEVEL <= LEVEL_WARN) {                                             \
      std::string s = std::string("[WARN]  %s:%d (%s) - ") + fmt + "\n";       \
      printf(s.c_str(), __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);      \
    }                                                                          \
  } while (0)
#define log_error(fmt, ...)                                                    \
  do {                                                                         \
    if (LOG_LEVEL <= LEVEL_ERROR) {                                            \
      std::string s = std::string("[ERROR] %s:%d (%s) - ") + fmt + "\n";       \
      printf(s.c_str(), __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);      \
    }                                                                          \
  } while (0)

#endif
