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

#ifndef FILECONTENT_H
#define FILECONTENT_H
#include <vector>
#include <map>
#include <unordered_set>
#include "TimeInfo.h"
#include "DesignElement.h"
#include "DesignComponent.h"
#include "ValuedComponentI.h"
#include "VObject.h"
#include "SourceCompile/VObjectTypes.h"

namespace SURELOG {

class Library;
class ModuleDefinition;
class Package;
class Program;
class ClassDefinition;
class ExprBuilder;
class ErrorContainer;

typedef std::map<std::string, ModuleDefinition*> ModuleNameModuleDefinitionMap;
typedef std::multimap<std::string, Package*>
    PackageNamePackageDefinitionMultiMap;
typedef std::vector<Package*> PackageDefinitionVec;
typedef std::map<std::string, Program*> ProgramNameProgramDefinitionMap;

typedef std::multimap<std::string, ClassDefinition*>
    ClassNameClassDefinitionMultiMap;
typedef std::map<std::string, ClassDefinition*> ClassNameClassDefinitionMap;

class FileContent : public DesignComponent {
 public:
  FileContent(SymbolId fileId, Library* library, SymbolTable* symbolTable,
              ErrorContainer* errors, FileContent* parent, SymbolId fileChunkId)
      : DesignComponent(NULL),
        m_fileId(fileId),
        m_library(library),
        m_symbolTable(symbolTable),
        m_errors(errors),
        m_parentFile(parent),
        m_fileChunkId(fileChunkId) {}
  void setLibrary(Library* lib) { m_library = lib; }
  virtual ~FileContent();

  typedef std::unordered_map<std::string, NodeId> NameIdMap;

  NodeId sl_get(NodeId parent,
                VObjectType type);  // Get first child item of type

  NodeId sl_parent(NodeId parent,
                   VObjectType type);  // Get first parent item of type

  NodeId sl_parent(NodeId parent, std::vector<VObjectType> types,
                   VObjectType& actualType);  // Get first parent item of type

  std::vector<NodeId> sl_get_all(
      NodeId parent, VObjectType type);  // get all child items of type

  std::vector<NodeId> sl_get_all(
      NodeId parent,
      std::vector<VObjectType>& types);  // get all child items of types

  NodeId sl_collect(
      NodeId parent,
      VObjectType type);  // Recursively search for first item of type

  NodeId sl_collect(
      NodeId parent, VObjectType type,
      VObjectType stopType);  // Recursively search for first item of type

  std::vector<NodeId> sl_collect_all(
      NodeId parent, VObjectType type,
      bool first = false);  // Recursively search for all items of type

  std::vector<NodeId> sl_collect_all(
      NodeId parent, std::vector<VObjectType>& types,
      bool first = false);  // Recursively search for all items of types

  std::vector<NodeId> sl_collect_all(NodeId parent,
                                     std::vector<VObjectType>& types,
                                     std::vector<VObjectType>& stopPoints,
                                     bool first = false);
  // Recursively search for all items of types
  // and stops at types stopPoints
  unsigned int getSize();
  VObjectType getType() { return VObjectType::slNoType; }
  bool isInstance() { return false; }
  std::string getName() { return m_symbolTable->getSymbol(m_fileId); }
  NodeId getRootNode();
  std::string printObjects();                    // The whole file content
  std::string printSubTree(NodeId parentIndex);  // Print subtree from parent
  std::vector<std::string> collectSubTree(NodeId uniqueId);  // Helper function
  std::string getFileName(NodeId id);
  std::string getChunkFileName() {
    return m_symbolTable->getSymbol(m_fileChunkId);
  }
  SymbolTable* getSymbolTable() { return m_symbolTable; }
  void setSymbolTable(SymbolTable* table) { m_symbolTable = table; }
  SymbolId& getFileId(NodeId id);
  Library* getLibrary() { return m_library; }
  std::vector<DesignElement>& getDesignElements() { return m_elements; }
  std::vector<VObject>& getVObjects() { return m_objects; }
  NameIdMap& getObjectLookup() { return m_objectLookup; }
  void insertObjectLookup(std::string name, NodeId id, ErrorContainer* errors);
  std::unordered_set<std::string>& getReferencedObjects() {
    return m_referencedObjects;
  }

  VObject& Object(NodeId index);

  NodeId UniqueId(NodeId index);

  SymbolId& Name(NodeId index);

  NodeId& Child(NodeId index);

  NodeId& Sibling(NodeId index);

  NodeId& Definition(NodeId index);

  void SetDefinitionFile(NodeId index, SymbolId def);
  SymbolId GetDefinitionFile(NodeId index);

  NodeId& Parent(NodeId index);

  VObjectType Type(NodeId index);

  unsigned int& Line(NodeId index);

  std::string SymName(NodeId index) {
    return m_symbolTable->getSymbol(Name(index));
  }

  ModuleNameModuleDefinitionMap& getModuleDefinitions() {
    return m_moduleDefinitions;
  }
  PackageNamePackageDefinitionMultiMap& getPackageDefinitions() {
    return m_packageDefinitions;
  }
  ProgramNameProgramDefinitionMap& getProgramDefinitions() {
    return m_programDefinitions;
  }
  ClassNameClassDefinitionMultiMap& getClassDefinitions() {
    return m_classDefinitions;
  }
  void addModuleDefinition(std::string moduleName, ModuleDefinition* def) {
    m_moduleDefinitions.insert(std::make_pair(moduleName, def));
  }
  void addPackageDefinition(std::string packageName, Package* package) {
    m_packageDefinitions.insert(std::make_pair(packageName, package));
  }
  void addProgramDefinition(std::string programName, Program* program) {
    m_programDefinitions.insert(std::make_pair(programName, program));
  }
  void addClassDefinition(std::string className, ClassDefinition* classDef) {
    m_classDefinitions.insert(std::make_pair(className, classDef));
  }

  ModuleDefinition* getModuleDefinition(const std::string& moduleName);

  DesignComponent* getComponentDefinition(const std::string& componentName);

  Package* getPackage(const std::string& name);

  Program* getProgram(const std::string& name);

  ClassDefinition* getClassDefinition(const std::string& name);

  FileContent* getParent() { return m_parentFile; }
  void setParent(FileContent* parent) { m_parentFile = parent; }

  std::string getFileName() { return m_symbolTable->getSymbol(m_fileId); }

  bool diffTree(std::string& diff, NodeId id, FileContent* oFc, NodeId oId);

 private:
  std::vector<DesignElement> m_elements;

  std::vector<VObject> m_objects;
  std::unordered_map<NodeId, SymbolId> m_definitionFiles;

  NameIdMap m_objectLookup;  // Populated at ResolveSymbol stage
  std::unordered_set<std::string> m_referencedObjects;

  ModuleNameModuleDefinitionMap m_moduleDefinitions;

  PackageNamePackageDefinitionMultiMap m_packageDefinitions;

  ProgramNameProgramDefinitionMap m_programDefinitions;

  ClassNameClassDefinitionMultiMap m_classDefinitions;

  SymbolId m_fileId;
  Library* m_library;
  SymbolTable* m_symbolTable;
  ErrorContainer* m_errors;
  FileContent* m_parentFile;  // for file chunks
  SymbolId m_fileChunkId;
};

};  // namespace SURELOG

#endif /* FILECONTENT_H */
