/*
 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:   FileContent.cpp
 * Author: alain
 *
 * Created on June 8, 2017, 8:22 PM
 */

#include "SourceCompile/SymbolTable.h"
#include "Design/TimeInfo.h"
#include "Design/DesignElement.h"
#include "Library/Library.h"
#include "ErrorReporting/ErrorContainer.h"
#include "Design/FileContent.h"
#include <queue>
#include <iostream>
#include <stack>
#include <string.h>

using namespace SURELOG;

FileContent::~FileContent() {}

NodeId FileContent::getRootNode() {
  if (m_objects.size() == 0) {
    return 0;
  }
  return m_objects[0].m_sibling;
}

SymbolId& FileContent::getFileId(NodeId id) { return m_objects[id].m_fileId; }

std::string FileContent::getFileName(NodeId id) {
  SymbolId fileId = m_objects[id].m_fileId;
  return m_symbolTable->getSymbol(fileId);
}

std::string FileContent::printObjects() {
  std::string text;
  NodeId index = 0;

  if (m_library) text += "LIB:  " + m_library->getName() + "\n";
  std::string fileName = m_symbolTable->getSymbol(m_fileId);
  if (strstr(fileName.c_str(), "builtin.sv"))
    return "";
  text += "FILE: " + fileName + "\n";

  for (auto object : m_objects) {
    text += object.print(m_symbolTable, index, GetDefinitionFile(index));
    text += "\n";
    index++;
  }
  return text;
}

unsigned int FileContent::getSize() { return m_objects.size(); }

std::string FileContent::printSubTree(NodeId uniqueId) {
  std::string text;
  for (auto s : collectSubTree(uniqueId)) {
    text += s + "\n";
  }
  return text;
}

void FileContent::insertObjectLookup(std::string name, NodeId id,
                                     ErrorContainer* errors) {
  NameIdMap::iterator itr = m_objectLookup.find(name);
  if (itr == m_objectLookup.end()) {
    m_objectLookup.insert(std::make_pair(name, id));
  } else {
    Location loc(errors->getSymbolTable()->registerSymbol(getFileName(id)),
                 Line(id), 0, errors->getSymbolTable()->registerSymbol(name));
    Location loc2(
        errors->getSymbolTable()->registerSymbol(getFileName((*itr).second)),
        Line((*itr).second), 0);
    Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_DESIGN_UNIT, loc, loc2);
    errors->addError(err);
  }
}

ModuleDefinition* FileContent::getModuleDefinition(
    const std::string& moduleName) {
  ModuleNameModuleDefinitionMap::iterator itr =
      m_moduleDefinitions.find(moduleName);
  if (itr != m_moduleDefinitions.end()) {
    return (*itr).second;
  }
  return NULL;
}

DesignComponent* FileContent::getComponentDefinition(
    const std::string& componentName) {
  DesignComponent* comp = (DesignComponent*)getModuleDefinition(componentName);
  if (comp) return comp;
  comp = (DesignComponent*)getProgram(componentName);
  if (comp) return comp;
  comp = (DesignComponent*)getClassDefinition(componentName);
  if (comp) return comp;
  return NULL;
}

Package* FileContent::getPackage(const std::string& name) {
  PackageNamePackageDefinitionMultiMap::iterator itr =
      m_packageDefinitions.find(name);
  if (itr == m_packageDefinitions.end()) {
    return NULL;
  } else {
    return (*itr).second;
  }
}

Program* FileContent::getProgram(const std::string& name) {
  ProgramNameProgramDefinitionMap::iterator itr =
      m_programDefinitions.find(name);
  if (itr == m_programDefinitions.end()) {
    return NULL;
  } else {
    return (*itr).second;
  }
}

ClassDefinition* FileContent::getClassDefinition(const std::string& name) {
  ClassNameClassDefinitionMultiMap::iterator itr =
      m_classDefinitions.find(name);
  if (itr == m_classDefinitions.end()) {
    return NULL;
  } else {
    return (*itr).second;
  }
}

std::vector<std::string> FileContent::collectSubTree(NodeId index) {
  std::vector<std::string> text;

  text.push_back(
      m_objects[index].print(m_symbolTable, index, GetDefinitionFile(index)));

  if (m_objects[index].m_child) {
    for (auto s : collectSubTree(m_objects[index].m_child)) {
      text.push_back("    " + s);
    }
  }

  if (m_objects[index].m_sibling) {
    for (auto s : collectSubTree(m_objects[index].m_sibling)) {
      text.push_back(s);
    }
  }

  return text;
}

void FileContent::SetDefinitionFile(NodeId index, SymbolId def) {
  m_definitionFiles.insert(std::make_pair(index, def));
}

SymbolId FileContent::GetDefinitionFile(NodeId index) {
  auto itr = m_definitionFiles.find(index);
  if (itr != m_definitionFiles.end()) return (*itr).second;
  return 0;
}

VObject& FileContent::Object(NodeId index) { return m_objects[index]; }

NodeId FileContent::UniqueId(NodeId index) { return index; }

SymbolId& FileContent::Name(NodeId index) { return m_objects[index].m_name; }

NodeId& FileContent::Child(NodeId index) { return m_objects[index].m_child; }

NodeId& FileContent::Sibling(NodeId index) {
  return m_objects[index].m_sibling;
}

NodeId& FileContent::Definition(NodeId index) {
  return m_objects[index].m_definition;
}

NodeId& FileContent::Parent(NodeId index) { return m_objects[index].m_parent; }

VObjectType FileContent::Type(NodeId index) {
  return (VObjectType)m_objects[index].m_type;
}

unsigned int& FileContent::Line(NodeId index) {
  return m_objects[index].m_line;
}

NodeId FileContent::sl_get(NodeId parent, VObjectType type) {
  if (!m_objects.size()) return 0;
  if (parent > m_objects.size() - 1) return 0;
  VObject current = Object(parent);
  if (current.m_type == type) return parent;
  NodeId id = current.m_child;
  while (id) {
    current = Object(id);
    if (current.m_type == type) {
      return id;
    }
    id = current.m_sibling;
  }
  return InvalidNodeId;
}

NodeId FileContent::sl_parent(NodeId parent, std::vector<VObjectType> types,
                              VObjectType& actualType) {
  if (!m_objects.size()) return 0;
  if (parent > m_objects.size() - 1) return 0;
  VObject current = Object(parent);
  for (auto type : types)
    if (current.m_type == type) {
      actualType = type;
      return parent;
    }
  NodeId id = current.m_parent;
  while (id) {
    current = Object(id);
    for (auto type : types)
      if (current.m_type == type) {
        actualType = type;
        return id;
      }
    id = current.m_parent;
  }
  return InvalidNodeId;
}

NodeId FileContent::sl_parent(NodeId parent, VObjectType type) {
  if (!m_objects.size()) return 0;
  if (parent > m_objects.size() - 1) return 0;
  VObject current = Object(parent);
  if (current.m_type == type) return parent;
  NodeId id = current.m_parent;
  while (id) {
    current = Object(id);
    if (current.m_type == type) {
      return id;
    }
    id = current.m_parent;
  }
  return InvalidNodeId;
}

std::vector<NodeId> FileContent::sl_get_all(NodeId parent, VObjectType type) {
  std::vector<NodeId> objects;
  if (!m_objects.size()) return objects;
  if (parent > m_objects.size() - 1) return objects;
  VObject current = Object(parent);
  if (current.m_type == type) objects.push_back(parent);
  NodeId id = current.m_child;
  while (id) {
    current = Object(id);
    if (current.m_type == type) {
      objects.push_back(id);
    }
    id = current.m_sibling;
  }
  return objects;
}

std::vector<NodeId> FileContent::sl_get_all(NodeId parent,
                                            std::vector<VObjectType>& types) {
  std::vector<NodeId> objects;
  if (!m_objects.size()) return objects;
  if (parent > m_objects.size() - 1) return objects;
  VObject current = Object(parent);
  for (auto type : types) {
    if (current.m_type == type) {
      objects.push_back(parent);
      break;
    }
  }

  NodeId id = current.m_child;
  while (id) {
    current = Object(id);
    for (auto type : types) {
      if (current.m_type == type) {
        objects.push_back(id);
        break;
      }
    }
    id = current.m_sibling;
  }
  return objects;
}

NodeId FileContent::sl_collect(NodeId parent, VObjectType type) {
  if (!m_objects.size()) return 0;
  if (parent > m_objects.size() - 1) return 0;
  VObject current = Object(parent);
  if (current.m_type == type) return parent;
  NodeId id = current.m_child;
  while (id) {
    NodeId idsub = sl_collect(id, type);
    if (idsub != InvalidNodeId) {
      return idsub;
    }
    current = Object(id);
    if (current.m_type == type) {
      return id;
    }
    id = current.m_sibling;
  }
  return InvalidNodeId;
}

std::vector<NodeId> FileContent::sl_collect_all(NodeId parent, VObjectType type,
                                                bool first) {
  std::vector<NodeId> objects;
  if (!m_objects.size()) return objects;
  if (parent > m_objects.size() - 1) return objects;
  VObject current = Object(parent);
  NodeId id = current.m_child;
  if (!id) id = current.m_sibling;
  if (!id) return objects;
  std::stack<NodeId> stack;
  stack.push(id);
  while (stack.size()) {
    id = stack.top();
    stack.pop();
    current = Object(id);
    if (current.m_type == type) {
      objects.push_back(id);
      if (first) return objects;
    }
    if (current.m_sibling) stack.push(current.m_sibling);
    if (current.m_child) stack.push(current.m_child);
  }
  return objects;
}

std::vector<NodeId> FileContent::sl_collect_all(NodeId parent,
                                                std::vector<VObjectType>& types,
                                                bool first) {
  std::vector<NodeId> objects;
  if (!m_objects.size()) return objects;
  if (parent > m_objects.size() - 1) return objects;
  VObject current = Object(parent);
  NodeId id = current.m_child;
  if (!id) id = current.m_sibling;
  if (!id) return objects;
  std::stack<NodeId> stack;
  stack.push(id);
  while (stack.size()) {
    id = stack.top();
    stack.pop();
    current = Object(id);
    // std::cout << "COLLECT:" << current.print (m_symbolTable, id,
    // GetDefinitionFile(id)) << std::endl;
    for (auto type : types) {
      if (current.m_type == type) {
        objects.push_back(id);
        if (first) return objects;
        break;
      }
    }
    if (current.m_sibling) stack.push(current.m_sibling);
    if (current.m_child) stack.push(current.m_child);
  }
  return objects;
}

NodeId FileContent::sl_collect(NodeId parent, VObjectType type,
                               VObjectType stopPoint) {
  NodeId result = InvalidNodeId;
  if (!m_objects.size()) return result;
  if (parent > m_objects.size() - 1) return result;
  VObject current = Object(parent);
  NodeId id = current.m_child;
  if (!id) id = current.m_sibling;
  if (!id) return result;
  std::stack<NodeId> stack;
  stack.push(id);
  while (stack.size()) {
    id = stack.top();
    stack.pop();
    current = Object(id);
    if (current.m_type == type) {
      return id;
    }

    if (current.m_sibling) stack.push(current.m_sibling);

    if (current.m_child) {
      if (stopPoint != current.m_type)
        if (current.m_child) stack.push(current.m_child);
    }
  }
  return result;
}

std::vector<NodeId> FileContent::sl_collect_all(
    NodeId parent, std::vector<VObjectType>& types,
    std::vector<VObjectType>& stopPoints, bool first) {
  std::vector<NodeId> objects;
  if (!m_objects.size()) return objects;
  if (parent > m_objects.size() - 1) return objects;
  VObject current = Object(parent);
  NodeId id = current.m_child;
  if (!id) id = current.m_sibling;
  if (!id) return objects;
  std::stack<NodeId> stack;
  stack.push(id);
  while (stack.size()) {
    id = stack.top();
    stack.pop();
    current = Object(id);
    // std::cout << "COLLECT:" << current.print (m_symbolTable, id,
    // GetDefinitionFile(id)) << std::endl;
    for (auto type : types) {
      if (current.m_type == type) {
        objects.push_back(id);
        if (first) return objects;
        break;
      }
    }
    if (current.m_sibling) stack.push(current.m_sibling);

    if (current.m_child) {
      if (stopPoints.size()) {
        bool stop = false;
        for (auto t : stopPoints) {
          if (t == current.m_type) {
            stop = true;
            break;
          }
        }
        if (!stop)
          if (current.m_child) stack.push(current.m_child);
      } else {
        if (current.m_child) stack.push(current.m_child);
      }
    }
  }
  return objects;
}

bool FileContent::diffTree(std::string& diff, NodeId root, FileContent* oFc,
                           NodeId oroot) {
  diff = "";

  VObject current1 = Object(root);
  NodeId id1 = current1.m_child;
  if (!id1) id1 = current1.m_sibling;

  VObject current2 = oFc->Object(oroot);
  NodeId id2 = current2.m_child;
  if (!id2) id2 = current2.m_sibling;

  if ((id1 && (!id2)) || ((!id1) && id2)) return true;

  std::stack<NodeId> stack1;
  std::stack<NodeId> stack2;
  stack1.push(id1);
  stack2.push(id2);
  while (stack1.size()) {
    if (!stack2.size()) return true;
    id1 = stack1.top();
    id2 = stack2.top();
    stack1.pop();
    stack2.pop();
    current1 = Object(id1);
    current2 = oFc->Object(id2);
    if (current1.m_type != current2.m_type) {
      return true;
    }
    std::string symb1;
    std::string symb2;
    if (current1.m_name) symb1 = Name(id1);
    if (current2.m_name) symb2 = oFc->Name(id2);
    if (current1.m_name || current2.m_name)
      if (symb1 != symb2) return true;

    if (current1.m_sibling) stack1.push(current1.m_sibling);
    if (current1.m_child) stack1.push(current1.m_child);
    if (current2.m_sibling) stack2.push(current2.m_sibling);
    if (current2.m_child) stack2.push(current2.m_child);
  }
  if (stack2.size()) return true;
  return false;
}
