/*
 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.h"
#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/Cache.h"
#include "Cache/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;
}
