/*
 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:   ParseCache.cpp
 * Author: alain
 *
 * Created on April 29, 2017, 4:20 PM
 */

#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <cstdio>
#include <ctime>

#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 "SourceCompile/ParseFile.h"
#include "Utils/StringUtils.h"
#include "Utils/FileUtils.h"
#include "Cache/Cache.h"
#include "flatbuffers/util.h"
#include "Cache/ParseCache.h"
#include "Design/FileContent.h"
#include "Package/Precompiled.h"

using namespace SURELOG;

ParseCache::ParseCache(ParseFile* parser)
    : m_parse(parser), m_isPrecompiled(false) {}

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

ParseCache::~ParseCache() {}

static std::string FlbSchemaVersion = "1.0";

std::string ParseCache::getCacheFileName_(std::string svFileName) {
  Precompiled* prec = Precompiled::getSingleton();
  SymbolId cacheDirId =
      m_parse->getCompileSourceFile()->getCommandLineParser()->getCacheDir();
  if (svFileName == "") svFileName = m_parse->getPpFileName();
  std::string root = svFileName;
  root = StringUtils::getRootFileName(root);
  if (prec->isFilePrecompiled(root)) {
    std::string packageRepDir =
        m_parse->getSymbol(m_parse->getCompileSourceFile()
                               ->getCommandLineParser()
                               ->getPrecompiledDir());
    cacheDirId = m_parse->getCompileSourceFile()
                     ->getCommandLineParser()
                     ->getSymbolTable()
                     ->registerSymbol(packageRepDir);
    m_isPrecompiled = true;
  }

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

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

  /* Restore Errors */
  const PARSECACHE::ParseCache* ppcache =
      PARSECACHE::GetParseCache(buffer_pointer);
  SymbolTable canonicalSymbols;
  restoreErrors(ppcache->m_errors(), ppcache->m_symbols(), canonicalSymbols,
                m_parse->getCompileSourceFile()->getErrorContainer(),
                m_parse->getCompileSourceFile()->getSymbolTable());
  /* Restore design content (Verilog Design Elements) */
  FileContent* fileContent = m_parse->getFileContent();
  if (fileContent == NULL) {
    fileContent = new FileContent(
        m_parse->getFileId(0), m_parse->getLibrary(),
        m_parse->getCompileSourceFile()->getSymbolTable(),
        m_parse->getCompileSourceFile()->getErrorContainer(), NULL, 0);
    m_parse->setFileContent(fileContent);
    m_parse->getCompileSourceFile()->getCompiler()->getDesign()->addFileContent(
        m_parse->getFileId(0), fileContent);
  }
  auto content = ppcache->m_elements();
  for (unsigned int i = 0; i < content->Length(); i++) {
    auto elemc = content->Get(i);
    DesignElement elem(
        m_parse->getCompileSourceFile()->getSymbolTable()->registerSymbol(
            canonicalSymbols.getSymbol(elemc->m_name())),
        m_parse->getCompileSourceFile()->getSymbolTable()->registerSymbol(
            canonicalSymbols.getSymbol(elemc->m_fileId())),
        (DesignElement::ElemType)elemc->m_type(), elemc->m_uniqueId(),
        elemc->m_line(), elemc->m_parent());
    elem.m_node = elemc->m_node();
    elem.m_timeInfo.m_type = (TimeInfo::Type)elemc->m_timeInfo()->m_type();
    elem.m_timeInfo.m_fileId = elemc->m_timeInfo()->m_fileId();
    elem.m_timeInfo.m_line = elemc->m_timeInfo()->m_line();
    elem.m_timeInfo.m_timeUnit =
        (TimeInfo::Unit)elemc->m_timeInfo()->m_timeUnit();
    elem.m_timeInfo.m_timeUnitValue = elemc->m_timeInfo()->m_timeUnitValue();
    elem.m_timeInfo.m_timePrecision =
        (TimeInfo::Unit)elemc->m_timeInfo()->m_timePrecision();
    elem.m_timeInfo.m_timePrecisionValue =
        elemc->m_timeInfo()->m_timePrecisionValue();
    fileContent->getDesignElements().push_back(elem);
  }

  /* Restore design objects */
  auto objects = ppcache->m_objects();
  for (unsigned int i = 0; i < objects->Length(); i++) {
    auto objectc = objects->Get(i);

    // VObject object
    // (m_parse->getCompileSourceFile()->getSymbolTable()->registerSymbol(canonicalSymbols.getSymbol(objectc->m_name())),
    //                (VObjectType) objectc->m_type(), objectc->m_uniqueId(),
    //                objectc->m_line(), objectc->m_parent(),
    //                objectc->m_definition(),
    //               objectc->m_child(),  objectc->m_sibling());

    unsigned long field1 = objectc->m_field1();
    unsigned long field2 = objectc->m_field2();
    unsigned long field3 = objectc->m_field3();
    // Decode compression done when saving cache (see below)
    SymbolId name = (field1 & 0x00000000000FFFFF);
    unsigned short type = (field1 & 0x00000000FFF00000) >> (20);
    // UNUSED: unsigned int   line  = (field1 & 0x0000FFFF00000000) >> (20 +
    // 12);
    NodeId parent = (field1 & 0xFFFF000000000000) >> (20 + 12 + 16);
    parent |= (field2 & 0x000000000000000F) << (16);
    NodeId definition = (field2 & 0x0000000000FFFFF0) >> (4);
    NodeId child = (field2 & 0x00000FFFFF000000) >> (4 + 20);
    NodeId sibling = (field2 & 0xFFFFF00000000000) >> (4 + 20 + 20);
    SymbolId fileId = (field3 & 0x00000000FFFFFFFF);
    unsigned int line = (field3 & 0xFFFFFFFF00000000) >> (32);
    VObject object(
        m_parse->getCompileSourceFile()->getSymbolTable()->registerSymbol(
            canonicalSymbols.getSymbol(name)),
        m_parse->getCompileSourceFile()->getSymbolTable()->registerSymbol(
            canonicalSymbols.getSymbol(fileId)),
        (VObjectType)type, line, parent, definition, child, sibling);

    fileContent->getVObjects().push_back(object);
  }
  // std::cout << "RESTORE: " << cacheFileName << " "
  //          << m_parse->getCompileSourceFile()->getSymbolTable()->getSymbol
  //          (m_parse->getFileId(0))
  //          << " NB: " <<  objects->Length()
  //          << std::endl;

  delete[] buffer_pointer;
  return true;
}

bool ParseCache::checkCacheIsValid_(std::string cacheFileName) {
  uint8_t* buffer_pointer = openFlatBuffers(cacheFileName);
  if (buffer_pointer == NULL) return false;
  if (!PARSECACHE::ParseCacheBufferHasIdentifier(buffer_pointer)) {
    delete[] buffer_pointer;
    return false;
  }
  const PARSECACHE::ParseCache* ppcache =
      PARSECACHE::GetParseCache(buffer_pointer);
  auto header = ppcache->m_header();

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

  delete[] buffer_pointer;
  return true;
}

bool ParseCache::isValid() {
  std::string cacheFileName = getCacheFileName_();
  return checkCacheIsValid_(cacheFileName);
}

bool ParseCache::restore() {
  bool cacheAllowed =
      m_parse->getCompileSourceFile()->getCommandLineParser()->cacheAllowed();
  if (!cacheAllowed) return false;

  std::string cacheFileName = getCacheFileName_();
  if (!checkCacheIsValid_(cacheFileName)) {
    return false;
  }

  return restore_(cacheFileName);
}

bool ParseCache::save() {
  bool cacheAllowed =
      m_parse->getCompileSourceFile()->getCommandLineParser()->cacheAllowed();
  if (!cacheAllowed) return true;
  std::string svFileName = m_parse->getPpFileName();
  std::string origFileName = svFileName;

  std::string cacheFileName = getCacheFileName_();

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

  /* Cache the errors and canonical symbols */
  ErrorContainer* errorContainer =
      m_parse->getCompileSourceFile()->getErrorContainer();
  std::string subjectFile = m_parse->getFileName(LINE1);
  SymbolId subjectFileId =
      m_parse->getCompileSourceFile()->getSymbolTable()->registerSymbol(
          subjectFile);
  SymbolTable canonicalSymbols;
  auto errorSymbolPair = cacheErrors(
      builder, canonicalSymbols, errorContainer,
      m_parse->getCompileSourceFile()->getSymbolTable(), subjectFileId);

  /* Cache the design content */
  FileContent* fcontent = m_parse->getFileContent();
  std::vector<flatbuffers::Offset<PARSECACHE::DesignElement>> element_vec;
  for (unsigned int i = 0; i < fcontent->getDesignElements().size(); i++) {
    DesignElement& elem = fcontent->getDesignElements()[i];
    TimeInfo& info = elem.m_timeInfo;
    auto timeInfo = CACHE::CreateTimeInfo(
        builder, info.m_type,
        canonicalSymbols.getId(
            m_parse->getCompileSourceFile()->getSymbolTable()->getSymbol(
                info.m_fileId)),
        info.m_line, info.m_timeUnit, info.m_timeUnitValue,
        info.m_timePrecision, info.m_timePrecisionValue);
    element_vec.push_back(PARSECACHE::CreateDesignElement(
        builder,
        canonicalSymbols.getId(
            m_parse->getCompileSourceFile()->getSymbolTable()->getSymbol(
                elem.m_name)),
        canonicalSymbols.getId(
            m_parse->getCompileSourceFile()->getSymbolTable()->getSymbol(
                elem.m_fileId)),
        elem.m_type, elem.m_uniqueId, elem.m_line, timeInfo, elem.m_parent,
        elem.m_node));
  }
  auto elementList = builder.CreateVector(element_vec);

  /* Cache the design objects */
  // std::vector<flatbuffers::Offset<PARSECACHE::VObject>> object_vec;
  std::vector<PARSECACHE::VObject> object_vec;
  for (size_t i = 0; i < fcontent->getVObjects().size(); i++) {
    VObject& object = fcontent->getVObjects()[i];

    // Lets compress this struct into 20 and 16 bits fields:
    //  object_vec.push_back(PARSECACHE::CreateVObject(builder,
    //                                              canonicalSymbols.getId(m_parse->getCompileSourceFile()->getSymbolTable()->getSymbol(object.m_name)),
    //                                              object.m_uniqueId,
    //                                              object.m_type,
    //                                              object.m_line,
    //                                              object.m_parent,
    //                                               object.m_definition,
    //                                               object.m_child,
    //                                               object.m_sibling));

    uint64_t field1 = 0;
    uint64_t field2 = 0;
    uint64_t field3 = 0;
    SymbolId name = canonicalSymbols.getId(
        m_parse->getCompileSourceFile()->getSymbolTable()->getSymbol(
            object.m_name));
    field1 |= (name);  // 20 Bits => Filled 20 Bits (Of 64)
    field1 |= (((unsigned long)object.m_type)
               << (20));  // 12 Bits => Filled 32 Bits (Of 64)
    // UNUSED: field1 |= (((unsigned long) object.m_line)   << (20 + 12)); // 16
    // Bits => Filled 48 Bits (Of 64)
    field1 |=
        ((uint64_t)object.m_parent
         << (20 + 12 + 16));  // 16 Bits => Filled 64 Bits (Of 64) , Word Full
    field2 |= (object.m_parent >> (16));  //  4 Bits => Filled  4 Bits (Of 64)
    field2 |=
        (object.m_definition << (4));  // 20 Bits => Filled 24 Bits (Of 64)
    field2 |= (((uint64_t)object.m_child)
               << (4 + 20));  // 20 Bits => Filled 44 Bits (Of 64)
    field2 |=
        (((uint64_t)object.m_sibling)
         << (4 + 20 + 20));  // 20 Bits => Filled 64 Bits (Of 64) , Word Full
    field3 |= object.m_fileId;
    field3 |= (((uint64_t)object.m_line) << (32));
    PARSECACHE::VObject vostruct(field1, field2, field3);
    object_vec.push_back(vostruct);
  }
  // auto objectList = builder.CreateVector(object_vec);
  auto objectList = builder.CreateVectorOfStructs(object_vec);

  // std::cout << "SAVE: " << cacheFileName << " "
  //          << m_parse->getCompileSourceFile()->getSymbolTable()->getSymbol
  //          (m_parse->getFileId(0))
  //          << " NB: " <<   fcontent->getVObjects().size()
  //         << std::endl;

  /* Create Flatbuffers */
  auto ppcache = PARSECACHE::CreateParseCache(
      builder, header, errorSymbolPair.first, errorSymbolPair.second,
      elementList, objectList);
  FinishParseCacheBuffer(builder, ppcache);

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

  return status;
}
