/*
 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/Cache.h"
#include "CommandLine/CommandLineParser.h"
#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() {}
