/*
 Copyright 2019 Alain Dargelas

 Licensed 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.
 */

/*
 * File:   Cache.cpp
 * Author: alain
 *
 * Created on April 28, 2017, 9:32 PM
 */

#include <cstdio>
#include <ctime>
#include <sys/types.h>
#include <sys/stat.h>
#include <iostream>
#include "../SourceCompile/SymbolTable.h"
#include "../ErrorReporting/ErrorContainer.h"
#include "Cache.h"
#include "../CommandLine/CommandLineParser.hpp"
#include "flatbuffers/util.h"

using namespace SURELOG;

std::string ExecTimeStamp = std::string(__DATE__) + "-" + __TIME__;

std::string Cache::getExecutableTimeStamp() { return ExecTimeStamp; }

time_t Cache::get_mtime(const char* path) {
  struct stat statbuf;
  if (stat(path, &statbuf) == -1) {
    return -1;
  }
  return statbuf.st_mtime;
}

uint8_t* Cache::openFlatBuffers(std::string cacheFileName) {
  FILE* file = fopen(cacheFileName.c_str(), "rb");
  if (file == NULL) return NULL;
  fseek(file, 0L, SEEK_END);
  unsigned int length = ftell(file);
  fseek(file, 0L, SEEK_SET);
  char* data = new char[length];
  size_t l = fread(data, sizeof(char), length, file);
  fclose(file);
  if (length != l) {
    return NULL;
  }
  uint8_t* buffer_pointer = (uint8_t*)data;
  return buffer_pointer;
}

bool Cache::checkIfCacheIsValid(const SURELOG::CACHE::Header* header,
                                std::string schemaVersion,
                                std::string cacheFileName) {
  /* Schema version */
  if (schemaVersion != header->m_flb_version()->c_str()) {
    return false;
  }

  /* Tool version */
  if (CommandLineParser::getVersionNumber() !=
      header->m_sl_version()->c_str()) {
    return false;
  }

  /* Timestamp Tool that created Cache vs tool date */
  std::string execDate = getExecutableTimeStamp();
  if (execDate != header->m_sl_date_compiled()->c_str()) {
    return false;
  }

  /* Timestamp Cache vs Orig File */
  if (cacheFileName != "") {
    time_t ct = get_mtime(cacheFileName.c_str());
    std::string fileName = header->m_file()->c_str();
    time_t ft = get_mtime(fileName.c_str());
    if (ft == -1) return false;
    if (ct == -1) return false;
    if (ct < ft) return false;
  }

  return true;
}

const flatbuffers::Offset<SURELOG::CACHE::Header> Cache::createHeader(
    flatbuffers::FlatBufferBuilder& builder, std::string schemaVersion,
    std::string origFileName) {
  auto fName = builder.CreateString(origFileName);
  auto sl_version = builder.CreateString(CommandLineParser::getVersionNumber());
  auto sl_build_date = builder.CreateString(getExecutableTimeStamp());
  auto sl_flb_version = builder.CreateString(schemaVersion);
  std::time_t t_result = std::time(nullptr);
  auto file_creation_date = builder.CreateString(std::to_string(t_result));
  auto header = CACHE::CreateHeader(builder, sl_version, sl_flb_version,
                                    sl_build_date, file_creation_date, fName);
  return header;
}

bool Cache::saveFlatbuffers(flatbuffers::FlatBufferBuilder& builder,
                            std::string cacheFileName) {
  const unsigned char* buf = builder.GetBufferPointer();
  int size = builder.GetSize();
  bool status =
      flatbuffers::SaveFile(cacheFileName.c_str(), (char*)buf, size, true);
  return status;
}

std::pair<flatbuffers::Offset<
              flatbuffers::Vector<flatbuffers::Offset<SURELOG::CACHE::Error>>>,
          flatbuffers::Offset<
              flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>>
Cache::cacheErrors(flatbuffers::FlatBufferBuilder& builder,
                   SymbolTable& canonicalSymbols,
                   ErrorContainer* errorContainer, SymbolTable* symbols,
                   SymbolId subjectId) {
  std::vector<Error>& errors = errorContainer->getErrors();
  std::vector<flatbuffers::Offset<SURELOG::CACHE::Error>> error_vec;
  for (unsigned int i = 0; i < errors.size(); i++) {
    Error& error = errors[i];
    std::vector<Location>& locs = error.getLocations();
    if (locs.size()) {
      bool matchSubject = false;
      for (unsigned int j = 0; j < locs.size(); j++) {
        if (locs[j].m_fileId == subjectId) {
          matchSubject = true;
          break;
        }
      }
      if (matchSubject) {
        std::vector<flatbuffers::Offset<SURELOG::CACHE::Location>> location_vec;
        for (unsigned int j = 0; j < locs.size(); j++) {
          Location& loc = locs[j];
          SymbolId canonicalFileId =
              canonicalSymbols.registerSymbol(symbols->getSymbol(loc.m_fileId));
          SymbolId canonicalObjectId =
              canonicalSymbols.registerSymbol(symbols->getSymbol(loc.m_object));
          auto locflb =
              CACHE::CreateLocation(builder, canonicalFileId, loc.m_line,
                                    loc.m_column, canonicalObjectId);
          location_vec.push_back(locflb);
        }
        auto locvec = builder.CreateVector(location_vec);
        auto err = CACHE::CreateError(builder, locvec, error.getType());
        error_vec.push_back(err);
      }
    }
  }

  /* Cache all the symbols */
  for (auto itr = symbols->getSymbols().begin();
       itr != symbols->getSymbols().end(); itr++) {
    canonicalSymbols.registerSymbol(*itr);
  }

  auto symbolVec = builder.CreateVectorOfStrings(canonicalSymbols.getSymbols());
  auto errvec = builder.CreateVector(error_vec);
  return std::make_pair(errvec, symbolVec);
}

void Cache::restoreErrors(
    const flatbuffers::Vector<flatbuffers::Offset<SURELOG::CACHE::Error>>*
        errorsBuf,
    const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>*
        symbolsBuf,
    SymbolTable& canonicalSymbols, ErrorContainer* errorContainer,
    SymbolTable* symbols) {
  for (unsigned int i = 0; i < symbolsBuf->Length(); i++) {
    const std::string symbol = symbolsBuf->Get(i)->c_str();
    canonicalSymbols.registerSymbol(symbol);
  }
  for (unsigned int i = 0; i < errorsBuf->Length(); i++) {
    auto errorFlb = errorsBuf->Get(i);
    std::vector<Location> locs;
    for (unsigned int j = 0; j < errorFlb->m_locations()->Length(); j++) {
      auto locFlb = errorFlb->m_locations()->Get(j);
      SymbolId translFileId = symbols->registerSymbol(
          canonicalSymbols.getSymbol(locFlb->m_fileId()));
      SymbolId translObjectId = symbols->registerSymbol(
          canonicalSymbols.getSymbol(locFlb->m_object()));
      Location loc(translFileId, locFlb->m_line(), locFlb->m_column(),
                   translObjectId);
      locs.push_back(loc);
    }
    Error err((ErrorDefinition::ErrorType)errorFlb->m_errorId(), locs);
    errorContainer->addError(err, false);
  }
}

Cache::Cache() {}

Cache::Cache(const Cache& orig) {}

Cache::~Cache() {}
