/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#ifndef cmQtAutoMocUic_h
#define cmQtAutoMocUic_h

#include "cmConfigure.h" // IWYU pragma: keep

#include "cmFileTime.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
#include "cmWorkerPool.h"
#include "cmsys/RegularExpression.hxx"

#include <atomic>
#include <cstddef>
#include <map>
#include <memory> // IWYU pragma: keep
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

class cmMakefile;

/** \class cmQtAutoMocUic
 * \brief AUTOMOC and AUTOUIC generator
 */
class cmQtAutoMocUic : public cmQtAutoGenerator
{
public:
  cmQtAutoMocUic();
  ~cmQtAutoMocUic() override;

  cmQtAutoMocUic(cmQtAutoMocUic const&) = delete;
  cmQtAutoMocUic& operator=(cmQtAutoMocUic const&) = delete;

public:
  // -- Types

  /**
   * Search key plus regular expression pair
   */
  struct KeyExpT
  {
    KeyExpT() = default;

    KeyExpT(const char* key, const char* exp)
      : Key(key)
      , Exp(exp)
    {
    }

    KeyExpT(std::string key, std::string const& exp)
      : Key(std::move(key))
      , Exp(exp)
    {
    }

    std::string Key;
    cmsys::RegularExpression Exp;
  };

  /**
   * Include string with sub parts
   */
  struct IncludeKeyT
  {
    IncludeKeyT(std::string const& key, std::size_t basePrefixLength);

    std::string Key;  // Full include string
    std::string Dir;  // Include directory
    std::string Base; // Base part of the include file name
  };

  /**
   * Source file parsing cache
   */
  class ParseCacheT
  {
  public:
    // -- Types
    /**
     * Entry of the file parsing cache
     */
    struct FileT
    {
      void Clear();

      struct MocT
      {
        std::string Macro;
        struct IncludeT
        {
          std::vector<IncludeKeyT> Underscore;
          std::vector<IncludeKeyT> Dot;
        } Include;
        std::vector<std::string> Depends;
      } Moc;

      struct UicT
      {
        std::vector<IncludeKeyT> Include;
        std::vector<std::string> Depends;
      } Uic;
    };
    typedef std::shared_ptr<FileT> FileHandleT;
    typedef std::pair<FileHandleT, bool> GetOrInsertT;

  public:
    ParseCacheT();
    ~ParseCacheT();

    void Clear();

    bool ReadFromFile(std::string const& fileName);
    bool WriteToFile(std::string const& fileName);

    //! Might return an invalid handle
    FileHandleT Get(std::string const& fileName) const;
    //! Always returns a valid handle
    GetOrInsertT GetOrInsert(std::string const& fileName);

  private:
    std::unordered_map<std::string, FileHandleT> Map_;
  };

  /**
   * Source file data
   */
  class SourceFileT
  {
  public:
    SourceFileT(std::string fileName)
      : FileName(std::move(fileName))
    {
    }

  public:
    std::string FileName;
    cmFileTime FileTime;
    ParseCacheT::FileHandleT ParseData;
    std::string BuildPath;
    bool Moc = false;
    bool Uic = false;
  };
  typedef std::shared_ptr<SourceFileT> SourceFileHandleT;
  typedef std::map<std::string, SourceFileHandleT> SourceFileMapT;

  /**
   * Meta compiler file mapping information
   */
  struct MappingT
  {
    SourceFileHandleT SourceFile;
    std::string OutputFile;
    std::string IncludeString;
    std::vector<SourceFileHandleT> IncluderFiles;
  };
  typedef std::shared_ptr<MappingT> MappingHandleT;
  typedef std::map<std::string, MappingHandleT> MappingMapT;

  /**
   * Common settings
   */
  class BaseSettingsT
  {
  public:
    // -- Constructors
    BaseSettingsT();
    ~BaseSettingsT();

    BaseSettingsT(BaseSettingsT const&) = delete;
    BaseSettingsT& operator=(BaseSettingsT const&) = delete;

    // -- Attributes
    // - Config
    bool MultiConfig = false;
    bool IncludeProjectDirsBefore = false;
    unsigned int QtVersionMajor = 4;
    // - Directories
    std::string ProjectSourceDir;
    std::string ProjectBinaryDir;
    std::string CurrentSourceDir;
    std::string CurrentBinaryDir;
    std::string AutogenBuildDir;
    std::string AutogenIncludeDir;
    // - Files
    std::string CMakeExecutable;
    cmFileTime CMakeExecutableTime;
    std::string ParseCacheFile;
    std::vector<std::string> HeaderExtensions;
  };

  /**
   * Shared common variables
   */
  class BaseEvalT
  {
  public:
    // -- Parse Cache
    bool ParseCacheChanged = false;
    cmFileTime ParseCacheTime;
    ParseCacheT ParseCache;

    // -- Sources
    SourceFileMapT Headers;
    SourceFileMapT Sources;
  };

  /**
   * Moc settings
   */
  class MocSettingsT
  {
  public:
    // -- Constructors
    MocSettingsT();
    ~MocSettingsT();

    MocSettingsT(MocSettingsT const&) = delete;
    MocSettingsT& operator=(MocSettingsT const&) = delete;

    // -- Const methods
    bool skipped(std::string const& fileName) const;
    std::string MacrosString() const;

    // -- Attributes
    bool Enabled = false;
    bool SettingsChanged = false;
    bool RelaxedMode = false;
    cmFileTime ExecutableTime;
    std::string Executable;
    std::string CompFileAbs;
    std::string PredefsFileRel;
    std::string PredefsFileAbs;
    std::unordered_set<std::string> SkipList;
    std::vector<std::string> IncludePaths;
    std::vector<std::string> Includes;
    std::vector<std::string> Definitions;
    std::vector<std::string> Options;
    std::vector<std::string> AllOptions;
    std::vector<std::string> PredefsCmd;
    std::vector<KeyExpT> DependFilters;
    std::vector<KeyExpT> MacroFilters;
    cmsys::RegularExpression RegExpInclude;
  };

  /**
   * Moc shared variables
   */
  class MocEvalT
  {
  public:
    // -- predefines file
    cmFileTime PredefsTime;
    // -- Mappings
    MappingMapT HeaderMappings;
    MappingMapT SourceMappings;
    MappingMapT Includes;
    // -- Discovered files
    SourceFileMapT HeadersDiscovered;
    // -- Mocs compilation
    bool CompUpdated = false;
    std::vector<std::string> CompFiles;
  };

  /**
   * Uic settings
   */
  class UicSettingsT
  {
  public:
    UicSettingsT();
    ~UicSettingsT();

    UicSettingsT(UicSettingsT const&) = delete;
    UicSettingsT& operator=(UicSettingsT const&) = delete;

    // -- Const methods
    bool skipped(std::string const& fileName) const;

    // -- Attributes
    bool Enabled = false;
    bool SettingsChanged = false;
    cmFileTime ExecutableTime;
    std::string Executable;
    std::unordered_set<std::string> SkipList;
    std::vector<std::string> TargetOptions;
    std::map<std::string, std::vector<std::string>> Options;
    std::vector<std::string> SearchPaths;
    cmsys::RegularExpression RegExpInclude;
  };

  /**
   * Uic shared variables
   */
  class UicEvalT
  {
  public:
    SourceFileMapT UiFiles;
    MappingMapT Includes;
  };

  /**
   * Abstract job class for concurrent job processing
   */
  class JobT : public cmWorkerPool::JobT
  {
  protected:
    /**
     * @brief Protected default constructor
     */
    JobT(bool fence = false)
      : cmWorkerPool::JobT(fence)
    {
    }

    //! Get the generator. Only valid during Process() call!
    cmQtAutoMocUic* Gen() const
    {
      return static_cast<cmQtAutoMocUic*>(UserData());
    };

    // -- Accessors. Only valid during Process() call!
    Logger const& Log() const { return Gen()->Log(); }
    BaseSettingsT const& BaseConst() const { return Gen()->BaseConst(); }
    BaseEvalT& BaseEval() const { return Gen()->BaseEval(); }
    MocSettingsT const& MocConst() const { return Gen()->MocConst(); }
    MocEvalT& MocEval() const { return Gen()->MocEval(); }
    UicSettingsT const& UicConst() const { return Gen()->UicConst(); }
    UicEvalT& UicEval() const { return Gen()->UicEval(); }

    // -- Error logging with automatic abort
    void LogError(GenT genType, std::string const& message) const;
    void LogFileError(GenT genType, std::string const& filename,
                      std::string const& message) const;
    void LogCommandError(GenT genType, std::string const& message,
                         std::vector<std::string> const& command,
                         std::string const& output) const;

    /**
     * @brief Run an external process. Use only during Process() call!
     */
    bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
                    std::vector<std::string> const& command,
                    std::string* infoMessage = nullptr);
  };

  /**
   * Fence job utility class
   */
  class JobFenceT : public JobT
  {
  public:
    JobFenceT()
      : JobT(true)
    {
    }
    void Process() override{};
  };

  /**
   * Generate moc_predefs.h
   */
  class JobMocPredefsT : public JobFenceT
  {
    void Process() override;
    bool Update(std::string* reason) const;
  };

  /**
   * File parse job base class
   */
  class JobParseT : public JobT
  {
  public:
    JobParseT(SourceFileHandleT fileHandle)
      : FileHandle(std::move(fileHandle))
    {
    }

  protected:
    bool ReadFile();
    void CreateKeys(std::vector<IncludeKeyT>& container,
                    std::set<std::string> const& source,
                    std::size_t basePrefixLength);
    void MocMacro();
    void MocDependecies();
    void MocIncludes();
    void UicIncludes();

  protected:
    SourceFileHandleT FileHandle;
    std::string Content;
  };

  /**
   * Header file parse job
   */
  class JobParseHeaderT : public JobParseT
  {
  public:
    using JobParseT::JobParseT;
    void Process() override;
  };

  /**
   * Source file parse job
   */
  class JobParseSourceT : public JobParseT
  {
  public:
    using JobParseT::JobParseT;
    void Process() override;
  };

  /**
   * Evaluate parsed files
   */
  class JobEvaluateT : public JobFenceT
  {
    void Process() override;

    // -- Moc
    bool MocEvalHeader(SourceFileHandleT source);
    bool MocEvalSource(SourceFileHandleT const& source);
    SourceFileHandleT MocFindIncludedHeader(
      std::string const& includerDir, std::string const& includeBase) const;
    SourceFileHandleT MocFindHeader(std::string const& basePath) const;
    std::string MocMessageTestHeaders(std::string const& fileBase) const;
    bool MocRegisterIncluded(std::string const& includeString,
                             SourceFileHandleT includerFileHandle,
                             SourceFileHandleT sourceFileHandle,
                             bool sourceIsHeader) const;
    void MocRegisterMapping(MappingHandleT mappingHandle,
                            bool sourceIsHeader) const;

    // -- Uic
    bool UicEval(SourceFileMapT const& fileMap);
    bool UicEvalFile(SourceFileHandleT sourceFileHandle);
    SourceFileHandleT UicFindIncludedUi(std::string const& sourceFile,
                                        std::string const& sourceDir,
                                        IncludeKeyT const& incKey) const;
    bool UicRegisterMapping(std::string const& includeString,
                            SourceFileHandleT uiFileHandle,
                            SourceFileHandleT includerFileHandle);
  };

  /**
   * Generates moc/uic jobs
   */
  class JobGenerateT : public JobFenceT
  {
    void Process() override;
    // -- Moc
    bool MocGenerate(MappingHandleT const& mapping, bool compFile) const;
    bool MocUpdate(MappingT const& mapping, std::string* reason) const;
    std::pair<std::string, cmFileTime> MocFindDependency(
      std::string const& sourceDir, std::string const& includeString) const;
    // -- Uic
    bool UicGenerate(MappingHandleT const& mapping) const;
    bool UicUpdate(MappingT const& mapping, std::string* reason) const;
  };

  /**
   * File compiling base job
   */
  class JobCompileT : public JobT
  {
  public:
    JobCompileT(MappingHandleT uicMapping, std::unique_ptr<std::string> reason)
      : Mapping(std::move(uicMapping))
      , Reason(std::move(reason))
    {
    }

  protected:
    MappingHandleT Mapping;
    std::unique_ptr<std::string> Reason;
  };

  /**
   * moc compiles a file
   */
  class JobMocT : public JobCompileT
  {
  public:
    using JobCompileT::JobCompileT;
    void Process() override;
  };

  /**
   * uic compiles a file
   */
  class JobUicT : public JobCompileT
  {
  public:
    using JobCompileT::JobCompileT;
    void Process() override;
  };

  /// @brief Generate mocs_compilation.cpp
  ///
  class JobMocsCompilationT : public JobFenceT
  {
  private:
    void Process() override;
  };

  /// @brief The last job
  ///
  class JobFinishT : public JobFenceT
  {
  private:
    void Process() override;
  };

  // -- Const settings interface
  BaseSettingsT const& BaseConst() const { return this->BaseConst_; }
  BaseEvalT& BaseEval() { return this->BaseEval_; }
  MocSettingsT const& MocConst() const { return this->MocConst_; }
  MocEvalT& MocEval() { return this->MocEval_; }
  UicSettingsT const& UicConst() const { return this->UicConst_; }
  UicEvalT& UicEval() { return this->UicEval_; }

  // -- Parallel job processing interface
  cmWorkerPool& WorkerPool() { return WorkerPool_; }
  void AbortError() { Abort(true); }
  void AbortSuccess() { Abort(false); }

  // -- Utility
  std::string AbsoluteBuildPath(std::string const& relativePath) const;
  std::string AbsoluteIncludePath(std::string const& relativePath) const;
  template <class JOBTYPE>
  void CreateParseJobs(SourceFileMapT const& sourceMap);

private:
  // -- Utility accessors
  Logger const& Log() const { return Logger_; }
  // -- Abstract processing interface
  bool Init(cmMakefile* makefile) override;
  void InitJobs();
  bool Process() override;
  // -- Settings file
  void SettingsFileRead();
  bool SettingsFileWrite();
  // -- Parse cache
  void ParseCacheRead();
  bool ParseCacheWrite();
  // -- Thread processing
  void Abort(bool error);
  // -- Generation
  bool CreateDirectories();

private:
  // -- Utility
  Logger Logger_;
  // -- Settings
  BaseSettingsT BaseConst_;
  BaseEvalT BaseEval_;
  MocSettingsT MocConst_;
  MocEvalT MocEval_;
  UicSettingsT UicConst_;
  UicEvalT UicEval_;
  // -- Settings file
  std::string SettingsFile_;
  std::string SettingsStringMoc_;
  std::string SettingsStringUic_;
  // -- Worker thread pool
  std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
  cmWorkerPool WorkerPool_;
};

#endif
