/*
 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;
}
