/**
* 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 <cstdint>
#include <stdexcept>
#include <algorithm>
#include "TsBlock.h"

std::shared_ptr<TsBlock> TsBlock::create(int32_t positionCount, std::shared_ptr<Column> timeColumn,
                                         std::vector<std::shared_ptr<Column>> valueColumns) {
  if (valueColumns.empty()) {
    throw std::invalid_argument("valueColumns cannot be empty");
  }
  return std::shared_ptr<TsBlock>(
      new TsBlock(positionCount, std::move(timeColumn), std::move(valueColumns)));
}

std::shared_ptr<TsBlock> TsBlock::deserialize(const std::string& data) {
  MyStringBuffer buffer(data);

  // Read value column count
  int32_t valueColumnCount = buffer.getInt();
  if (valueColumnCount < 0) {
    throw IoTDBException("TsBlock::deserialize: negative valueColumnCount");
  }
  const int64_t minHeaderBytes = 9LL + 2LL * static_cast<int64_t>(valueColumnCount);
  if (minHeaderBytes > static_cast<int64_t>(data.size())) {
    throw IoTDBException("TsBlock::deserialize: truncated header");
  }

  // Read value column data types
  std::vector<TSDataType::TSDataType> valueColumnDataTypes(valueColumnCount);
  for (int32_t i = 0; i < valueColumnCount; i++) {
    valueColumnDataTypes[i] = static_cast<TSDataType::TSDataType>(buffer.getChar());
  }

  // Read position count
  int32_t positionCount = buffer.getInt();
  if (positionCount < 0) {
    throw IoTDBException("TsBlock::deserialize: negative positionCount");
  }

  // Read column encodings
  std::vector<ColumnEncoding> columnEncodings(valueColumnCount + 1);
  for (int32_t i = 0; i < valueColumnCount + 1; i++) {
    columnEncodings[i] = static_cast<ColumnEncoding>(buffer.getChar());
  }

  // Read time column
  auto timeColumnDecoder = getColumnDecoder(columnEncodings[0]);
  auto timeColumn = timeColumnDecoder->readColumn(buffer, TSDataType::INT64, positionCount);

  // Read value columns
  std::vector<std::shared_ptr<Column>> valueColumns(valueColumnCount);
  for (int32_t i = 0; i < valueColumnCount; i++) {
    auto valueColumnDecoder = getColumnDecoder(columnEncodings[i + 1]);
    valueColumns[i] =
        valueColumnDecoder->readColumn(buffer, valueColumnDataTypes[i], positionCount);
  }

  return create(positionCount, std::move(timeColumn), std::move(valueColumns));
}

TsBlock::TsBlock(int32_t positionCount, std::shared_ptr<Column> timeColumn,
                 std::vector<std::shared_ptr<Column>> valueColumns)
    : positionCount_(positionCount), timeColumn_(std::move(timeColumn)),
      valueColumns_(std::move(valueColumns)) {}

int32_t TsBlock::getPositionCount() const {
  return positionCount_;
}

int64_t TsBlock::getStartTime() const {
  return timeColumn_->getLong(0);
}

int64_t TsBlock::getEndTime() const {
  return timeColumn_->getLong(positionCount_ - 1);
}

bool TsBlock::isEmpty() const {
  return positionCount_ == 0;
}

int64_t TsBlock::getTimeByIndex(int32_t index) const {
  return timeColumn_->getLong(index);
}

int32_t TsBlock::getValueColumnCount() const {
  return static_cast<int32_t>(valueColumns_.size());
}

const std::shared_ptr<Column> TsBlock::getTimeColumn() const {
  return timeColumn_;
}

const std::vector<std::shared_ptr<Column>>& TsBlock::getValueColumns() const {
  return valueColumns_;
}

const std::shared_ptr<Column> TsBlock::getColumn(int32_t columnIndex) const {
  return valueColumns_[columnIndex];
}
