/*
 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:   PPCache.cpp
 * Author: alain
 *
 * Created on April 23, 2017, 8:49 PM
 */
#include "CommandLine/CommandLineParser.hpp"
#include "ErrorReporting/ErrorContainer.h"
#include "SourceCompile/SymbolTable.h"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/CompileSourceFile.h"
#include "SourceCompile/Compiler.h"
#include "Utils/StringUtils.h"
#include "Utils/FileUtils.h"
#include "Cache.h"
#include "PPCache.h"
#include "flatbuffers/util.h"
#include <cstdio>
#include <ctime>
#include <sys/types.h>
#include <sys/stat.h>
#include <algorithm>
#include "Package/Precompiled.h"
using namespace SURELOG;

PPCache::PPCache(PreprocessFile* pp) : m_pp(pp), m_isPrecompiled(false) {}

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

PPCache::~PPCache() {}

static std::string FlbSchemaVersion = "1.0";

std::string PPCache::getCacheFileName_(std::string svFileName) {
  Precompiled* prec = Precompiled::getSingleton();
  SymbolId cacheDirId =
      m_pp->getCompileSourceFile()->getCommandLineParser()->getCacheDir();

  if (svFileName == "") svFileName = m_pp->getFileName(LINE1);
  std::string root = svFileName;
  root = StringUtils::getRootFileName(root);
  if (prec->isFilePrecompiled(root)) {
    std::string packageRepDir = m_pp->getSymbol(m_pp->getCompileSourceFile()
                                                    ->getCommandLineParser()
                                                    ->getPrecompiledDir());
    cacheDirId = m_pp->getCompileSourceFile()
                     ->getCommandLineParser()
                     ->getSymbolTable()
                     ->registerSymbol(packageRepDir);
    m_isPrecompiled = true;
  }

  std::string cacheDirName = m_pp->getSymbol(cacheDirId);

  Library* lib = m_pp->getLibrary();
  std::string libName = lib->getName() + "/";
  svFileName = StringUtils::getRootFileName(svFileName);
  std::string cacheFileName = cacheDirName + libName + svFileName + ".slpp";
  FileUtils::mkDir(std::string(cacheDirName + libName).c_str());
  return cacheFileName;
}

template <class T>
static bool compareVectors(std::vector<T> a, std::vector<T> b) {
  std::sort(a.begin(), a.end());
  std::sort(b.begin(), b.end());
  return (a == b);
}

bool PPCache::restore_(std::string cacheFileName) {
  uint8_t* buffer_pointer = openFlatBuffers(cacheFileName);
  if (buffer_pointer == NULL) return false;

  const MACROCACHE::PPCache* ppcache = MACROCACHE::GetPPCache(buffer_pointer);

  const flatbuffers::Vector<flatbuffers::Offset<MACROCACHE::Macro>>* macros =
      ppcache->m_macros();
  for (unsigned int i = 0; i < macros->Length(); i++) {
    const MACROCACHE::Macro* macro = macros->Get(i);
    std::vector<std::string> args;
    std::vector<std::string> tokens;
    for (unsigned int j = 0; j < macro->m_arguments()->Length(); j++) {
      args.push_back(macro->m_arguments()->Get(j)->c_str());
    }
    for (unsigned int j = 0; j < macro->m_tokens()->Length(); j++) {
      tokens.push_back(macro->m_tokens()->Get(j)->c_str());
    }
    m_pp->recordMacro(macro->m_name()->c_str(), macro->m_line(),
                      macro->m_column(), args, tokens);
  }
  SymbolTable canonicalSymbols;
  restoreErrors(ppcache->m_errors(), ppcache->m_symbols(), canonicalSymbols,
                m_pp->getCompileSourceFile()->getErrorContainer(),
                m_pp->getCompileSourceFile()->getSymbolTable());

  /* Restore `timescale directives */
  const flatbuffers::Vector<flatbuffers::Offset<CACHE::TimeInfo>>* timeinfos =
      ppcache->m_timeInfo();
  for (unsigned int i = 0; i < timeinfos->Length(); i++) {
    const CACHE::TimeInfo* fbtimeinfo = timeinfos->Get(i);
    TimeInfo timeInfo;
    timeInfo.m_type = (TimeInfo::Type)fbtimeinfo->m_type();
    timeInfo.m_fileId = fbtimeinfo->m_fileId();
    timeInfo.m_line = fbtimeinfo->m_line();
    timeInfo.m_timeUnit = (TimeInfo::Unit)fbtimeinfo->m_timeUnit();
    timeInfo.m_timeUnitValue = fbtimeinfo->m_timeUnitValue();
    timeInfo.m_timePrecision = (TimeInfo::Unit)fbtimeinfo->m_timePrecision();
    timeInfo.m_timePrecisionValue = fbtimeinfo->m_timePrecisionValue();
    m_pp->getCompilationUnit()->recordTimeInfo(timeInfo);
  }

  auto includes = ppcache->m_includes();
  if (includes)
    for (unsigned int i = 0; i < includes->Length(); i++) {
      auto include = includes->Get(i);
      restore_(getCacheFileName_(include->c_str()));
    }
  if (ppcache->m_body() && ppcache->m_body()->c_str()) {
    m_pp->append(ppcache->m_body()->c_str());
  }
  delete[] buffer_pointer;
  return true;
}

bool PPCache::checkCacheIsValid_(std::string cacheFileName) {
  uint8_t* buffer_pointer = openFlatBuffers(cacheFileName);
  if (buffer_pointer == NULL) {
    delete[] buffer_pointer;
    return false;
  }
  if (!MACROCACHE::PPCacheBufferHasIdentifier(buffer_pointer)) {
    delete[] buffer_pointer;
    return false;
  }
  const MACROCACHE::PPCache* ppcache = MACROCACHE::GetPPCache(buffer_pointer);
  auto header = ppcache->m_header();

  if (!m_isPrecompiled) {
    if (!checkIfCacheIsValid(header, FlbSchemaVersion, cacheFileName)) {
      delete[] buffer_pointer;
      return false;
    }

    /* Cache the include paths list */
    auto includePathList =
        m_pp->getCompileSourceFile()->getCommandLineParser()->getIncludePaths();
    std::vector<std::string> include_path_vec;
    for (auto path : includePathList) {
      std::string spath = m_pp->getSymbol(path);
      include_path_vec.push_back(spath);
    }

    std::vector<std::string> cache_include_path_vec;
    for (unsigned int i = 0; i < ppcache->m_cmd_include_paths()->Length();
         i++) {
      const std::string path = ppcache->m_cmd_include_paths()->Get(i)->c_str();
      cache_include_path_vec.push_back(path);
    }
    if (!compareVectors(include_path_vec, cache_include_path_vec)) {
      delete[] buffer_pointer;
      return false;
    }

    /* Cache the defines on the command line */
    auto defineList =
        m_pp->getCompileSourceFile()->getCommandLineParser()->getDefineList();
    std::vector<std::string> define_vec;
    for (auto definePair : defineList) {
      std::string spath =
          m_pp->getSymbol(definePair.first) + "=" + definePair.second;
      define_vec.push_back(spath);
    }
    std::vector<std::string> cache_define_vec;
    for (unsigned int i = 0; i < ppcache->m_cmd_define_options()->Length();
         i++) {
      const std::string path = ppcache->m_cmd_define_options()->Get(i)->c_str();
      cache_define_vec.push_back(path);
    }
    if (!compareVectors(define_vec, cache_define_vec)) {
      delete[] buffer_pointer;
      return false;
    }

    /* All includes*/
    auto includes = ppcache->m_includes();
    if (includes)
      for (unsigned int i = 0; i < includes->Length(); i++) {
        auto include = includes->Get(i);
        if (!checkCacheIsValid_(getCacheFileName_(include->c_str()))) {
          delete[] buffer_pointer;
          return false;
        }
      }
  }

  delete[] buffer_pointer;
  return true;
}

bool PPCache::restore() {
  bool cacheAllowed =
      m_pp->getCompileSourceFile()->getCommandLineParser()->cacheAllowed();
  if (!cacheAllowed) return false;
  if (m_pp->isMacroBody()) return false;
  std::string cacheFileName = getCacheFileName_();
  if (!checkCacheIsValid_(cacheFileName)) {
    return false;
  }

  return restore_(cacheFileName);
}

bool PPCache::save() {
  bool cacheAllowed =
      m_pp->getCompileSourceFile()->getCommandLineParser()->cacheAllowed();
  if (!cacheAllowed) return false;
  std::string svFileName = m_pp->getFileName(LINE1);
  std::string origFileName = svFileName;

  std::string cacheFileName = getCacheFileName_();

  if (m_pp->isMacroBody()) return false;

  flatbuffers::FlatBufferBuilder builder(1024);
  /* Create header section */
  auto header = createHeader(builder, FlbSchemaVersion, origFileName);

  /* Cache the macro definitions */
  const MacroStorage& macros = m_pp->getMacros();
  std::vector<flatbuffers::Offset<MACROCACHE::Macro>> macro_vec;
  for (MacroStorage::const_iterator itr = macros.begin(); itr != macros.end();
       itr++) {
    std::string macroName = (*itr).first;
    MacroInfo* info = (*itr).second;

    auto name = builder.CreateString(macroName);
    MACROCACHE::MacroType type = (info->m_type == MacroInfo::WITH_ARGS)
                                     ? MACROCACHE::MacroType_WITH_ARGS
                                     : MACROCACHE::MacroType_NO_ARGS;
    auto args = builder.CreateVectorOfStrings(info->m_arguments);
    auto tokens = builder.CreateVectorOfStrings(info->m_tokens);
    macro_vec.push_back(MACROCACHE::CreateMacro(
        builder, name, type, info->m_line, info->m_column, args, tokens));
  }
  auto macroList = builder.CreateVector(macro_vec);

  /* Cache Included files */
  std::vector<std::string> include_vec;
  std::set<PreprocessFile*> included;
  m_pp->collectIncludedFiles(included);
  for (std::set<PreprocessFile*>::iterator itr = included.begin();
       itr != included.end(); itr++) {
    std::string svFileName = m_pp->getSymbol((*itr)->getRawFileId());
    include_vec.push_back(svFileName);
  }
  auto includeList = builder.CreateVectorOfStrings(include_vec);

  /* Cache the body of the file */
  auto body = builder.CreateString(m_pp->getPreProcessedFileContent());

  /* Cache the errors and canonical symbols */
  ErrorContainer* errorContainer =
      m_pp->getCompileSourceFile()->getErrorContainer();
  SymbolId subjectFileId = m_pp->getFileId(LINE1);
  SymbolTable canonicalSymbols;
  auto errorSymbolPair = cacheErrors(
      builder, canonicalSymbols, errorContainer,
      m_pp->getCompileSourceFile()->getSymbolTable(), subjectFileId);

  /* Cache the include paths list */
  auto includePathList =
      m_pp->getCompileSourceFile()->getCommandLineParser()->getIncludePaths();
  std::vector<std::string> include_path_vec;
  for (auto path : includePathList) {
    std::string spath = m_pp->getSymbol(path);
    include_path_vec.push_back(spath);
  }
  auto incPaths = builder.CreateVectorOfStrings(include_path_vec);

  /* Cache the defines on the command line */
  auto defineList =
      m_pp->getCompileSourceFile()->getCommandLineParser()->getDefineList();
  std::vector<std::string> define_vec;
  for (auto definePair : defineList) {
    std::string spath =
        m_pp->getSymbol(definePair.first) + "=" + definePair.second;
    define_vec.push_back(spath);
  }
  auto defines = builder.CreateVectorOfStrings(define_vec);

  /* Cache the `timescale directives */
  auto timeinfoList = m_pp->getCompilationUnit()->getTimeInfo();
  std::vector<flatbuffers::Offset<CACHE::TimeInfo>> timeinfo_vec;
  for (auto info : timeinfoList) {
    if (info.m_fileId != m_pp->getFileId(0)) continue;
    auto timeInfo = CACHE::CreateTimeInfo(
        builder, info.m_type,
        canonicalSymbols.getId(
            m_pp->getCompileSourceFile()->getSymbolTable()->getSymbol(
                info.m_fileId)),
        info.m_line, info.m_timeUnit, info.m_timeUnitValue,
        info.m_timePrecision, info.m_timePrecisionValue);
    timeinfo_vec.push_back(timeInfo);
  }
  auto timeinfoFBList = builder.CreateVector(timeinfo_vec);

  /* Create Flatbuffers */
  auto ppcache = MACROCACHE::CreatePPCache(
      builder, header, macroList, includeList, body, errorSymbolPair.first,
      errorSymbolPair.second, incPaths, defines, timeinfoFBList);
  FinishPPCacheBuffer(builder, ppcache);

  /* Save Flatbuffer */
  bool status = saveFlatbuffers(builder, cacheFileName);

  return status;
}
