/*
 * 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 "Session.h"

using namespace std;

Session *session;

#define DEFAULT_ROW_NUMBER 1000000

void createAlignedTimeseries() {
  string alignedDeviceId = "root.sg1.d1";
  vector<string> measurements = {"s1", "s2", "s3"};
  vector<string> alignedTimeseries = {"root.sg1.d1.s1", "root.sg1.d1.s2",
                                      "root.sg1.d1.s3"};
  vector<TSDataType::TSDataType> dataTypes = {
      TSDataType::INT32, TSDataType::DOUBLE, TSDataType::BOOLEAN};
  vector<TSEncoding::TSEncoding> encodings = {
      TSEncoding::PLAIN, TSEncoding::GORILLA, TSEncoding::RLE};
  vector<CompressionType::CompressionType> compressors = {
      CompressionType::SNAPPY, CompressionType::UNCOMPRESSED,
      CompressionType::SNAPPY};
  for (const string &timeseries : alignedTimeseries) {
    if (session->checkTimeseriesExists(timeseries)) {
      session->deleteTimeseries(timeseries);
    }
  }
  session->createAlignedTimeseries(alignedDeviceId, measurements, dataTypes,
                                   encodings, compressors);
}

void createSchemaTemplate() {
  if (!session->checkTemplateExists("template1")) {
    Template temp("template1", false);

    InternalNode iNodeD99("d99", true);

    MeasurementNode mNodeS1("s1", TSDataType::INT32, TSEncoding::RLE,
                            CompressionType::SNAPPY);
    MeasurementNode mNodeS2("s2", TSDataType::INT64, TSEncoding::RLE,
                            CompressionType::SNAPPY);
    MeasurementNode mNodeD99S1("s1", TSDataType::DOUBLE, TSEncoding::RLE,
                               CompressionType::SNAPPY);
    MeasurementNode mNodeD99S2("s2", TSDataType::BOOLEAN, TSEncoding::RLE,
                               CompressionType::SNAPPY);

    iNodeD99.addChild(mNodeD99S1);
    iNodeD99.addChild(mNodeD99S2);

    temp.addToTemplate(iNodeD99);
    temp.addToTemplate(mNodeS1);
    temp.addToTemplate(mNodeS2);

    session->createSchemaTemplate(temp);
    session->setSchemaTemplate("template1", "root.sg3.d1");
  }
}

void ActivateTemplate() {
  session->executeNonQueryStatement(
      "insert into root.sg3.d1(timestamp,s1, s2) values(200, 1, 1);");
}

void showDevices() {
  unique_ptr<SessionDataSet> dataSet =
      session->executeQueryStatement("show devices with database");
  for (const string &name : dataSet->getColumnNames()) {
    cout << name << "  ";
  }
  cout << endl;

  dataSet->setFetchSize(1024);
  while (dataSet->hasNext()) {
    cout << dataSet->next()->toString();
  }
  cout << endl;

  dataSet->closeOperationHandle();
}

void showTimeseries() {
  unique_ptr<SessionDataSet> dataSet =
      session->executeQueryStatement("show timeseries");
  for (const string &name : dataSet->getColumnNames()) {
    cout << name << "  ";
  }
  cout << endl;

  dataSet->setFetchSize(1024);
  while (dataSet->hasNext()) {
    cout << dataSet->next()->toString();
  }
  cout << endl;

  dataSet->closeOperationHandle();
}

void insertAlignedRecord() {
  string deviceId = "root.sg1.d1";
  vector<string> measurements;
  measurements.emplace_back("s1");
  measurements.emplace_back("s2");
  measurements.emplace_back("s3");

  for (int64_t time = 0; time < 10; time++) {
    vector<string> values;
    values.emplace_back("1");
    values.emplace_back("1.0");
    values.emplace_back("true");
    session->insertAlignedRecord(deviceId, time, measurements, values);
  }
}

void insertAlignedRecords() {
  string deviceId = "root.sg1.d1";
  vector<string> measurements;
  measurements.emplace_back("s1");
  measurements.emplace_back("s2");
  measurements.emplace_back("s3");

  vector<string> deviceIds;
  vector<vector<string>> measurementsList;
  vector<vector<string>> valuesList;
  vector<int64_t> timestamps;

  for (int64_t time = 10; time < 20; time++) {
    vector<string> values;
    values.emplace_back("1");
    values.emplace_back("1.0");
    values.emplace_back("true");

    deviceIds.push_back(deviceId);
    measurementsList.push_back(measurements);
    valuesList.push_back(values);
    timestamps.push_back(time);
    if (time != 10 && time % 10 == 0) {
      session->insertAlignedRecords(deviceIds, timestamps, measurementsList,
                                    valuesList);
      deviceIds.clear();
      measurementsList.clear();
      valuesList.clear();
      timestamps.clear();
    }
  }

  session->insertAlignedRecords(deviceIds, timestamps, measurementsList,
                                valuesList);
}

void insertAlignedTablet() {
  pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT32);
  pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::DOUBLE);
  pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::DOUBLE);
  vector<pair<string, TSDataType::TSDataType>> schemas;
  schemas.push_back(pairA);
  schemas.push_back(pairB);
  schemas.push_back(pairC);

  Tablet tablet("root.sg2.d2", schemas, 100000);
  tablet.setAligned(true);

  for (int64_t time = 0; time < DEFAULT_ROW_NUMBER; time++) {
    size_t row = tablet.rowSize++;
    tablet.timestamps[row] = time;
    int randVal1 = 123456;
    double randVal2 = 123456.1234;
    double randVal3 = 123456.1234;
    tablet.addValue(0, row, randVal1);
    tablet.addValue(1, row, randVal2);
    tablet.addValue(2, row, randVal3);
    if (tablet.rowSize == tablet.maxRowNumber) {
      session->insertTablet(tablet, true);
      tablet.reset();
    }
  }

  if (tablet.rowSize != 0) {
    session->insertTablet(tablet);
    tablet.reset();
  }
}

void insertAlignedTablets() {
  pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT32);
  pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::DOUBLE);
  pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::BOOLEAN);
  vector<pair<string, TSDataType::TSDataType>> schemas;
  schemas.push_back(pairA);
  schemas.push_back(pairB);
  schemas.push_back(pairC);

  Tablet tablet1("root.sg1.d1", schemas, 100);
  Tablet tablet2("root.sg1.d2", schemas, 100);
  Tablet tablet3("root.sg1.d3", schemas, 100);

  unordered_map<string, Tablet *> tabletMap;
  tabletMap["root.sg1.d1"] = &tablet1;
  tabletMap["root.sg1.d2"] = &tablet2;
  tabletMap["root.sg1.d3"] = &tablet3;

  for (int64_t time = 0; time < 20; time++) {
    size_t row1 = tablet1.rowSize++;
    size_t row2 = tablet2.rowSize++;
    size_t row3 = tablet3.rowSize++;
    tablet1.timestamps[row1] = time;
    tablet2.timestamps[row2] = time;
    tablet3.timestamps[row3] = time;

    int randVal11 = rand();
    int randVal12 = rand();
    int randVal13 = rand();
    tablet1.addValue(0, row1, randVal11);
    tablet2.addValue(0, row2, randVal12);
    tablet3.addValue(0, row3, randVal13);

    double randVal21 = rand() / 99.9;
    double randVal22 = rand() / 99.9;
    double randVal23 = rand() / 99.9;
    tablet1.addValue(1, row1, randVal21);
    tablet2.addValue(1, row2, randVal22);
    tablet3.addValue(1, row3, randVal23);

    bool randVal31 = (bool)(rand() % 2);
    bool randVal32 = (bool)(rand() % 2);
    bool randVal33 = (bool)(rand() % 2);
    tablet1.addValue(2, row1, randVal31);
    tablet2.addValue(2, row2, randVal32);
    tablet3.addValue(2, row3, randVal33);

    if (tablet1.rowSize == tablet1.maxRowNumber) {
      session->insertAlignedTablets(tabletMap, true);

      tablet1.reset();
      tablet2.reset();
      tablet3.reset();
    }
  }

  if (tablet1.rowSize != 0) {
    session->insertAlignedTablets(tabletMap, true);
    tablet1.reset();
    tablet2.reset();
    tablet3.reset();
  }
}

void insertNullableTabletWithAlignedTimeseries() {
  pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT32);
  pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
  pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::BOOLEAN);
  vector<pair<string, TSDataType::TSDataType>> schemas;
  schemas.push_back(pairA);
  schemas.push_back(pairB);
  schemas.push_back(pairC);

  Tablet tablet("root.sg1.d4", schemas, 20);
  tablet.setAligned(true);

  for (int64_t time = 0; time < 20; time++) {
    size_t row = tablet.rowSize++;
    tablet.timestamps[row] = time;
    for (int i = 0; i < 3; i++) {
      int randVal1 = rand();
      int64_t randVal2 = rand();
      bool randVal3 = (bool)(rand() % 2);
      if (i == 0) {
        tablet.addValue(i, row, randVal1);
      } else if (i == 1) {
        tablet.addValue(i, row, randVal2);
      } else {
        tablet.addValue(i, row, randVal3);
      }
      // mark null value
      if ((row % 3) == (unsigned int)i) {
        tablet.bitMaps[i].mark(row);
      }
    }
    if (tablet.rowSize == tablet.maxRowNumber) {
      session->insertTablet(tablet, true);
      tablet.reset();
    }
  }

  if (tablet.rowSize != 0) {
    session->insertTablet(tablet);
    tablet.reset();
  }
}

void query() {
  unique_ptr<SessionDataSet> dataSet =
      session->executeQueryStatement("select * from root.sg1.**");
  cout << "timestamp"
       << "  ";
  for (const string &name : dataSet->getColumnNames()) {
    cout << name << "  ";
  }
  cout << endl;

  dataSet->setFetchSize(1024);
  while (dataSet->hasNext()) {
    cout << dataSet->next()->toString();
  }
  cout << endl;

  dataSet->closeOperationHandle();
}

void deleteData() {
  string path = "root.**";
  int64_t deleteTime = 49;
  session->deleteData(path, deleteTime);
}

void deleteTimeseries() {
  vector<string> paths;
  vector<string> alignedTimeseries = {
      "root.sg1.d1.s1", "root.sg1.d1.s2", "root.sg1.d1.s3", "root.sg1.d1.s4",
      "root.sg1.d2.s1", "root.sg1.d2.s2", "root.sg1.d2.s3", "root.sg1.d3.s1",
      "root.sg1.d3.s2", "root.sg1.d3.s3", "root.sg1.d4.s1", "root.sg1.d4.s2",
      "root.sg1.d4.s3", "root.sg2.d2.s1", "root.sg2.d2.s2", "root.sg2.d2.s3",
  };
  for (const string &timeseries : alignedTimeseries) {
    if (session->checkTimeseriesExists(timeseries)) {
      paths.push_back(timeseries);
    }
  }
  session->deleteTimeseries(paths);
}

void deleteStorageGroups() {
  vector<string> storageGroups;
  storageGroups.emplace_back("root.sg1");
  storageGroups.emplace_back("root.sg2");
  session->deleteStorageGroups(storageGroups);
}

int main() {
  LOG_LEVEL = LEVEL_DEBUG;

  session = new Session("127.0.0.1", 6667, "root", "root");

  cout << "session open\n" << endl;
  session->open(false);

  cout << "setStorageGroup\n" << endl;
  try {
    session->setStorageGroup("root.sg1");
  } catch (IoTDBException &e) {
    string errorMessage(e.what());
    if (errorMessage.find("StorageGroupAlreadySetException") == string::npos) {
      cout << errorMessage << endl;
      // throw e;
    }
  }

  cout << "createAlignedTimeseries\n" << endl;
  createAlignedTimeseries();

  cout << "createSchemaTemplate\n" << endl;
  createSchemaTemplate();

  cout << "ActivateTemplate\n" << endl;
  ActivateTemplate();

  cout << "showDevices\n" << endl;
  showDevices();

  cout << "showTimeseries\n" << endl;
  showTimeseries();

  cout << "insertAlignedRecord\n" << endl;
  insertAlignedRecord();

  cout << "insertAlignedRecords\n" << endl;
  insertAlignedRecords();

  cout << "insertAlignedTablet" << endl;
  cout << "Insert " << DEFAULT_ROW_NUMBER << " records." << endl;
  time_t now1 = time(0);
  insertAlignedTablet();
  time_t now2 = time(0);
  time_t useTime = now2 - now1;
  cout << "Use time: " << useTime << "s.\n" << endl;

  cout << "insertAlignedTablets\n" << endl;
  insertAlignedTablets();

  cout << "insertNullableTabletWithAlignedTimeseries\n" << endl;
  insertNullableTabletWithAlignedTimeseries();

  cout << "query\n" << endl;
  query();

  cout << "deleteData\n" << endl;
  deleteData();

  cout << "deleteTimeseries\n" << endl;
  deleteTimeseries();

  cout << "deleteStorageGroups\n" << endl;
  deleteStorageGroups();

  cout << "session close\n" << endl;
  session->close();

  delete session;

  cout << "finished\n" << endl;
  return 0;
}
