
#include "FirstConfigure.h"

#include "QCMakeSizeType.h"
#include <QComboBox>
#include <QRadioButton>
#include <QSettings>
#include <QVBoxLayout>

#include "cmStringAlgorithms.h"

#include "Compilers.h"

StartCompilerSetup::StartCompilerSetup(QString defaultGeneratorPlatform,
                                       QString defaultGeneratorToolset,
                                       QWidget* p)
  : QWizardPage(p)
  , DefaultGeneratorPlatform(std::move(defaultGeneratorPlatform))
  , DefaultGeneratorToolset(std::move(defaultGeneratorToolset))
{
  QVBoxLayout* l = new QVBoxLayout(this);
  l->addWidget(new QLabel(tr("Specify the generator for this project")));
  this->GeneratorOptions = new QComboBox(this);
  l->addWidget(this->GeneratorOptions);

  // Add the generator platform
  this->PlatformFrame = CreatePlatformWidgets();
  l->addWidget(PlatformFrame);

  // Add the ability to specify toolset (-T parameter)
  this->ToolsetFrame = CreateToolsetWidgets();
  l->addWidget(ToolsetFrame);

  l->addSpacing(6);

  this->CompilerSetupOptions[0] =
    new QRadioButton(tr("Use default native compilers"), this);
  this->CompilerSetupOptions[1] =
    new QRadioButton(tr("Specify native compilers"), this);
  this->CompilerSetupOptions[2] =
    new QRadioButton(tr("Specify toolchain file for cross-compiling"), this);
  this->CompilerSetupOptions[3] =
    new QRadioButton(tr("Specify options for cross-compiling"), this);
  l->addWidget(this->CompilerSetupOptions[0]);
  l->addWidget(this->CompilerSetupOptions[1]);
  l->addWidget(this->CompilerSetupOptions[2]);
  l->addWidget(this->CompilerSetupOptions[3]);

  this->CompilerSetupOptions[0]->setChecked(true);

  QObject::connect(this->CompilerSetupOptions[0], &QRadioButton::toggled, this,
                   &StartCompilerSetup::onSelectionChanged);
  QObject::connect(this->CompilerSetupOptions[1], &QRadioButton::toggled, this,
                   &StartCompilerSetup::onSelectionChanged);
  QObject::connect(this->CompilerSetupOptions[2], &QRadioButton::toggled, this,
                   &StartCompilerSetup::onSelectionChanged);
  QObject::connect(this->CompilerSetupOptions[3], &QRadioButton::toggled, this,
                   &StartCompilerSetup::onSelectionChanged);
  QObject::connect(
    this->GeneratorOptions,
    static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
    this, &StartCompilerSetup::onGeneratorChanged);
}

QFrame* StartCompilerSetup::CreateToolsetWidgets()
{
  QFrame* frame = new QFrame(this);
  QVBoxLayout* l = new QVBoxLayout(frame);
  l->setContentsMargins(0, 0, 0, 0);

  ToolsetLabel = new QLabel(tr("Optional toolset to use (argument to -T)"));
  l->addWidget(ToolsetLabel);

  Toolset = new QLineEdit(frame);
  l->addWidget(Toolset);

  // Default to CMAKE_GENERATOR_TOOLSET env var if set
  if (!DefaultGeneratorToolset.isEmpty()) {
    this->Toolset->setText(DefaultGeneratorToolset);
  }
  return frame;
}

QFrame* StartCompilerSetup::CreatePlatformWidgets()
{
  QFrame* frame = new QFrame(this);
  QVBoxLayout* l = new QVBoxLayout(frame);
  l->setContentsMargins(0, 0, 0, 0);

  this->PlatformLabel = new QLabel(tr("Optional platform for generator"));
  l->addWidget(this->PlatformLabel);

  this->PlatformOptions = new QComboBox(frame);
  this->PlatformOptions->setEditable(true);

  l->addWidget(this->PlatformOptions);

  return frame;
}

StartCompilerSetup::~StartCompilerSetup() = default;

void StartCompilerSetup::setGenerators(
  std::vector<cmake::GeneratorInfo> const& gens)
{
  this->GeneratorOptions->clear();

  QStringList generator_list;

  for (cmake::GeneratorInfo const& gen : gens) {
    generator_list.append(QString::fromStdString(gen.name));

    if (gen.supportsPlatform) {
      this->GeneratorsSupportingPlatform.append(
        QString::fromStdString(gen.name));

      this->GeneratorDefaultPlatform[QString::fromStdString(gen.name)] =
        QString::fromStdString(gen.defaultPlatform);

      auto platformIt = gen.supportedPlatforms.cbegin();
      while (platformIt != gen.supportedPlatforms.cend()) {

        this->GeneratorSupportedPlatforms.insert(
          QString::fromStdString(gen.name),
          QString::fromStdString((*platformIt)));

        platformIt++;
      }
    }

    if (gen.supportsToolset) {
      this->GeneratorsSupportingToolset.append(
        QString::fromStdString(gen.name));
    }
  }

  this->GeneratorOptions->addItems(generator_list);
}

void StartCompilerSetup::setCurrentGenerator(QString const& gen)
{
  int idx = this->GeneratorOptions->findText(gen);
  if (idx != -1) {
    this->GeneratorOptions->setCurrentIndex(idx);
  }
}

void StartCompilerSetup::setPlatform(QString const& platform)
{
  this->PlatformOptions->setCurrentText(platform);
}

void StartCompilerSetup::setToolset(QString const& toolset)
{
  this->Toolset->setText(toolset);
}

void StartCompilerSetup::setCompilerOption(CompilerOption option)
{
  std::size_t index = 0;
  switch (option) {
    case CompilerOption::DefaultPreset:
      this->CompilerSetupOptions[0]->setText(
        tr("Use default preset compilers"));
      CM_FALLTHROUGH;
    case CompilerOption::DefaultNative:
      index = 0;
      break;
    case CompilerOption::SpecifyNative:
      index = 1;
      break;
    case CompilerOption::ToolchainFile:
      index = 2;
      break;
    case CompilerOption::Options:
      index = 3;
      break;
  }
  this->CompilerSetupOptions[index]->setChecked(true);
}

QString StartCompilerSetup::getGenerator() const
{
  return this->GeneratorOptions->currentText();
};

QString StartCompilerSetup::getPlatform() const
{
  return this->PlatformOptions->currentText();
};

QString StartCompilerSetup::getToolset() const
{
  return this->Toolset->text();
};

bool StartCompilerSetup::defaultSetup() const
{
  return this->CompilerSetupOptions[0]->isChecked();
}

bool StartCompilerSetup::compilerSetup() const
{
  return this->CompilerSetupOptions[1]->isChecked();
}

bool StartCompilerSetup::crossCompilerToolChainFile() const
{
  return this->CompilerSetupOptions[2]->isChecked();
}

bool StartCompilerSetup::crossCompilerSetup() const
{
  return this->CompilerSetupOptions[3]->isChecked();
}

void StartCompilerSetup::onSelectionChanged(bool on)
{
  if (on) {
    emit selectionChanged();
  }
}

void StartCompilerSetup::onGeneratorChanged(int index)
{
  QString name = this->GeneratorOptions->itemText(index);

  // Display the generator platform for the generators supporting it
  if (GeneratorsSupportingPlatform.contains(name)) {

    // Change the label title to include the default platform
    std::string label =
      cmStrCat("Optional platform for generator(if empty, generator uses: ",
               this->GeneratorDefaultPlatform[name].toStdString(), ')');
    this->PlatformLabel->setText(tr(label.c_str()));

    // Regenerate the list of supported platform
    this->PlatformOptions->clear();
    QStringList platform_list;
    platform_list.append("");

    QList<QString> platforms = this->GeneratorSupportedPlatforms.values(name);
    platform_list.append(platforms);

    this->PlatformOptions->addItems(platform_list);
    PlatformFrame->show();

    // Default to generator platform from environment
    if (!DefaultGeneratorPlatform.isEmpty()) {
      cm_qsizetype platform_index =
        platforms.indexOf(DefaultGeneratorPlatform);
      if (platform_index != -1) {
        // The index is off-by-one due to the first empty item added above.
        this->PlatformOptions->setCurrentIndex(
          static_cast<int>(platform_index + 1));
      }
    }
  } else {
    PlatformFrame->hide();
  }

  // Display the toolset box for the generators supporting it
  if (GeneratorsSupportingToolset.contains(name)) {
    ToolsetFrame->show();
  } else {
    ToolsetFrame->hide();
  }
}

int StartCompilerSetup::nextId() const
{
  if (compilerSetup()) {
    return NativeSetup;
  }
  if (crossCompilerSetup()) {
    return CrossSetup;
  }
  if (crossCompilerToolChainFile()) {
    return ToolchainSetup;
  }
  return -1;
}

NativeCompilerSetup::NativeCompilerSetup(QWidget* p)
  : QWizardPage(p)
{
  QVBoxLayout* l = new QVBoxLayout(this);
  QWidget* c = new QWidget(this);
  l->addWidget(c);
  this->setupUi(c);
}

NativeCompilerSetup::~NativeCompilerSetup() = default;

QString NativeCompilerSetup::getCCompiler() const
{
  return this->CCompiler->text();
}

void NativeCompilerSetup::setCCompiler(QString const& s)
{
  this->CCompiler->setText(s);
}

QString NativeCompilerSetup::getCXXCompiler() const
{
  return this->CXXCompiler->text();
}

void NativeCompilerSetup::setCXXCompiler(QString const& s)
{
  this->CXXCompiler->setText(s);
}

QString NativeCompilerSetup::getFortranCompiler() const
{
  return this->FortranCompiler->text();
}

void NativeCompilerSetup::setFortranCompiler(QString const& s)
{
  this->FortranCompiler->setText(s);
}

CrossCompilerSetup::CrossCompilerSetup(QWidget* p)
  : QWizardPage(p)
{
  this->setupUi(this);
  QWidget::setTabOrder(systemName, systemVersion);
  QWidget::setTabOrder(systemVersion, systemProcessor);
  QWidget::setTabOrder(systemProcessor, CrossCompilers->CCompiler);
  QWidget::setTabOrder(CrossCompilers->CCompiler, CrossCompilers->CXXCompiler);
  QWidget::setTabOrder(CrossCompilers->CXXCompiler,
                       CrossCompilers->FortranCompiler);
  QWidget::setTabOrder(CrossCompilers->FortranCompiler, crossFindRoot);
  QWidget::setTabOrder(crossFindRoot, crossProgramMode);
  QWidget::setTabOrder(crossProgramMode, crossLibraryMode);
  QWidget::setTabOrder(crossLibraryMode, crossIncludeMode);

  // fill in combo boxes
  QStringList modes;
  modes << tr("Search in Target Root, then native system");
  modes << tr("Search only in Target Root");
  modes << tr("Search only in native system");
  crossProgramMode->addItems(modes);
  crossLibraryMode->addItems(modes);
  crossIncludeMode->addItems(modes);
  crossProgramMode->setCurrentIndex(2);
  crossLibraryMode->setCurrentIndex(1);
  crossIncludeMode->setCurrentIndex(1);

  this->registerField("systemName*", this->systemName);
}

CrossCompilerSetup::~CrossCompilerSetup() = default;

QString CrossCompilerSetup::getCCompiler() const
{
  return this->CrossCompilers->CCompiler->text();
}

void CrossCompilerSetup::setCCompiler(QString const& s)
{
  this->CrossCompilers->CCompiler->setText(s);
}

QString CrossCompilerSetup::getCXXCompiler() const
{
  return this->CrossCompilers->CXXCompiler->text();
}

void CrossCompilerSetup::setCXXCompiler(QString const& s)
{
  this->CrossCompilers->CXXCompiler->setText(s);
}

QString CrossCompilerSetup::getFortranCompiler() const
{
  return this->CrossCompilers->FortranCompiler->text();
}

void CrossCompilerSetup::setFortranCompiler(QString const& s)
{
  this->CrossCompilers->FortranCompiler->setText(s);
}

QString CrossCompilerSetup::getSystem() const
{
  return this->systemName->text();
}

void CrossCompilerSetup::setSystem(QString const& t)
{
  this->systemName->setText(t);
}

QString CrossCompilerSetup::getVersion() const
{
  return this->systemVersion->text();
}

void CrossCompilerSetup::setVersion(QString const& t)
{
  this->systemVersion->setText(t);
}

QString CrossCompilerSetup::getProcessor() const
{
  return this->systemProcessor->text();
}

void CrossCompilerSetup::setProcessor(QString const& t)
{
  this->systemProcessor->setText(t);
}

QString CrossCompilerSetup::getFindRoot() const
{
  return this->crossFindRoot->text();
}

void CrossCompilerSetup::setFindRoot(QString const& t)
{
  this->crossFindRoot->setText(t);
}

int CrossCompilerSetup::getProgramMode() const
{
  return this->crossProgramMode->currentIndex();
}

int CrossCompilerSetup::getLibraryMode() const
{
  return this->crossLibraryMode->currentIndex();
}

int CrossCompilerSetup::getIncludeMode() const
{
  return this->crossIncludeMode->currentIndex();
}

void CrossCompilerSetup::setProgramMode(int m)
{
  this->crossProgramMode->setCurrentIndex(m);
}

void CrossCompilerSetup::setLibraryMode(int m)
{
  this->crossLibraryMode->setCurrentIndex(m);
}

void CrossCompilerSetup::setIncludeMode(int m)
{
  this->crossIncludeMode->setCurrentIndex(m);
}

ToolchainCompilerSetup::ToolchainCompilerSetup(QWidget* p)
  : QWizardPage(p)
{
  QVBoxLayout* l = new QVBoxLayout(this);
  l->addWidget(new QLabel(tr("Specify the Toolchain file")));
  this->ToolchainFile = new QCMakeFilePathEditor(this);
  l->addWidget(this->ToolchainFile);
}

ToolchainCompilerSetup::~ToolchainCompilerSetup() = default;

QString ToolchainCompilerSetup::toolchainFile() const
{
  return this->ToolchainFile->text();
}

void ToolchainCompilerSetup::setToolchainFile(QString const& t)
{
  this->ToolchainFile->setText(t);
}

FirstConfigure::FirstConfigure()
{
#ifdef _WIN32
  // FIXME(QTBUG-123853): Fix window style init for dark mode.
  this->setWizardStyle(this->wizardStyle());
#endif
  char const* env_generator = std::getenv("CMAKE_GENERATOR");
  char const* env_generator_platform = nullptr;
  char const* env_generator_toolset = nullptr;
  if (env_generator && std::strlen(env_generator)) {
    mDefaultGenerator = env_generator;
    env_generator_platform = std::getenv("CMAKE_GENERATOR_PLATFORM");
    env_generator_toolset = std::getenv("CMAKE_GENERATOR_TOOLSET");
  }

  if (!env_generator_platform) {
    env_generator_platform = "";
  }

  if (!env_generator_toolset) {
    env_generator_toolset = "";
  }

  // this->setOption(QWizard::HaveFinishButtonOnEarlyPages, true);
  this->mStartCompilerSetupPage = new StartCompilerSetup(
    env_generator_platform, env_generator_toolset, this);
  this->setPage(Start, this->mStartCompilerSetupPage);
  QObject::connect(this->mStartCompilerSetupPage,
                   &StartCompilerSetup::selectionChanged, this,
                   &FirstConfigure::restart);
  this->mNativeCompilerSetupPage = new NativeCompilerSetup(this);
  this->setPage(NativeSetup, this->mNativeCompilerSetupPage);

  this->mCrossCompilerSetupPage = new CrossCompilerSetup(this);
  this->setPage(CrossSetup, this->mCrossCompilerSetupPage);

  this->mToolchainCompilerSetupPage = new ToolchainCompilerSetup(this);
  this->setPage(ToolchainSetup, this->mToolchainCompilerSetupPage);
}

FirstConfigure::~FirstConfigure() = default;

void FirstConfigure::setGenerators(
  std::vector<cmake::GeneratorInfo> const& gens)
{
  this->mStartCompilerSetupPage->setGenerators(gens);
}

void FirstConfigure::setCurrentGenerator(QString const& gen)
{
  this->mStartCompilerSetupPage->setCurrentGenerator(gen);
}

void FirstConfigure::setPlatform(QString const& platform)
{
  this->mStartCompilerSetupPage->setPlatform(platform);
}

void FirstConfigure::setToolset(QString const& toolset)
{
  this->mStartCompilerSetupPage->setToolset(toolset);
}

void FirstConfigure::setCompilerOption(CompilerOption option)
{
  this->mStartCompilerSetupPage->setCompilerOption(option);
}

QString FirstConfigure::getGenerator() const
{
  return this->mStartCompilerSetupPage->getGenerator();
}

QString FirstConfigure::getPlatform() const
{
  return this->mStartCompilerSetupPage->getPlatform();
}

QString FirstConfigure::getToolset() const
{
  return this->mStartCompilerSetupPage->getToolset();
}

void FirstConfigure::loadFromSettings()
{
  QSettings settings;
  // restore generator
  settings.beginGroup("Settings/StartPath");
  QString lastGen = settings.value("LastGenerator").toString();
  this->setCurrentGenerator(lastGen);
  settings.endGroup();

  // restore compiler setup
  settings.beginGroup("Settings/Compiler");
  this->mNativeCompilerSetupPage->setCCompiler(
    settings.value("CCompiler").toString());
  this->mNativeCompilerSetupPage->setCXXCompiler(
    settings.value("CXXCompiler").toString());
  this->mNativeCompilerSetupPage->setFortranCompiler(
    settings.value("FortranCompiler").toString());
  settings.endGroup();

  // restore cross compiler setup
  settings.beginGroup("Settings/CrossCompiler");
  this->mCrossCompilerSetupPage->setCCompiler(
    settings.value("CCompiler").toString());
  this->mCrossCompilerSetupPage->setCXXCompiler(
    settings.value("CXXCompiler").toString());
  this->mCrossCompilerSetupPage->setFortranCompiler(
    settings.value("FortranCompiler").toString());
  this->mToolchainCompilerSetupPage->setToolchainFile(
    settings.value("ToolChainFile").toString());
  this->mCrossCompilerSetupPage->setSystem(
    settings.value("SystemName").toString());
  this->mCrossCompilerSetupPage->setVersion(
    settings.value("SystemVersion").toString());
  this->mCrossCompilerSetupPage->setProcessor(
    settings.value("SystemProcessor").toString());
  this->mCrossCompilerSetupPage->setFindRoot(
    settings.value("FindRoot").toString());
  this->mCrossCompilerSetupPage->setProgramMode(
    settings.value("ProgramMode", 0).toInt());
  this->mCrossCompilerSetupPage->setLibraryMode(
    settings.value("LibraryMode", 0).toInt());
  this->mCrossCompilerSetupPage->setIncludeMode(
    settings.value("IncludeMode", 0).toInt());
  settings.endGroup();

  // environment variables take precedence over application settings because...
  // - they're harder to set
  // - settings always exist after the program is run once, so the environment
  //     variables would never be used otherwise
  // - platform and toolset are populated only from environment variables, so
  //     this prevents them from being taken from environment, while the
  //     generator is taken from application settings
  if (!mDefaultGenerator.isEmpty()) {
    this->setCurrentGenerator(mDefaultGenerator);
  }
}

void FirstConfigure::saveToSettings()
{
  QSettings settings;

  // save generator
  settings.beginGroup("Settings/StartPath");
  QString lastGen = this->mStartCompilerSetupPage->getGenerator();
  settings.setValue("LastGenerator", lastGen);
  settings.endGroup();

  // save compiler setup
  settings.beginGroup("Settings/Compiler");
  settings.setValue("CCompiler",
                    this->mNativeCompilerSetupPage->getCCompiler());
  settings.setValue("CXXCompiler",
                    this->mNativeCompilerSetupPage->getCXXCompiler());
  settings.setValue("FortranCompiler",
                    this->mNativeCompilerSetupPage->getFortranCompiler());
  settings.endGroup();

  // save cross compiler setup
  settings.beginGroup("Settings/CrossCompiler");
  settings.setValue("CCompiler",
                    this->mCrossCompilerSetupPage->getCCompiler());
  settings.setValue("CXXCompiler",
                    this->mCrossCompilerSetupPage->getCXXCompiler());
  settings.setValue("FortranCompiler",
                    this->mCrossCompilerSetupPage->getFortranCompiler());
  settings.setValue("ToolChainFile", this->getCrossCompilerToolChainFile());
  settings.setValue("SystemName", this->mCrossCompilerSetupPage->getSystem());
  settings.setValue("SystemVersion",
                    this->mCrossCompilerSetupPage->getVersion());
  settings.setValue("SystemProcessor",
                    this->mCrossCompilerSetupPage->getProcessor());
  settings.setValue("FindRoot", this->mCrossCompilerSetupPage->getFindRoot());
  settings.setValue("ProgramMode",
                    this->mCrossCompilerSetupPage->getProgramMode());
  settings.setValue("LibraryMode",
                    this->mCrossCompilerSetupPage->getLibraryMode());
  settings.setValue("IncludeMode",
                    this->mCrossCompilerSetupPage->getIncludeMode());
  settings.endGroup();
}

bool FirstConfigure::defaultSetup() const
{
  return this->mStartCompilerSetupPage->defaultSetup();
}

bool FirstConfigure::compilerSetup() const
{
  return this->mStartCompilerSetupPage->compilerSetup();
}

bool FirstConfigure::crossCompilerSetup() const
{
  return this->mStartCompilerSetupPage->crossCompilerSetup();
}

bool FirstConfigure::crossCompilerToolChainFile() const
{
  return this->mStartCompilerSetupPage->crossCompilerToolChainFile();
}

QString FirstConfigure::getCrossCompilerToolChainFile() const
{
  return this->mToolchainCompilerSetupPage->toolchainFile();
}

QString FirstConfigure::getSystemName() const
{
  return this->mCrossCompilerSetupPage->getSystem();
}

QString FirstConfigure::getCCompiler() const
{
  if (this->compilerSetup()) {
    return this->mNativeCompilerSetupPage->getCCompiler();
  }
  if (this->crossCompilerSetup()) {
    return this->mCrossCompilerSetupPage->getCCompiler();
  }
  return QString();
}

QString FirstConfigure::getCXXCompiler() const
{
  if (this->compilerSetup()) {
    return this->mNativeCompilerSetupPage->getCXXCompiler();
  }
  if (this->crossCompilerSetup()) {
    return this->mCrossCompilerSetupPage->getCXXCompiler();
  }
  return QString();
}

QString FirstConfigure::getFortranCompiler() const
{
  if (this->compilerSetup()) {
    return this->mNativeCompilerSetupPage->getFortranCompiler();
  }
  if (this->crossCompilerSetup()) {
    return this->mCrossCompilerSetupPage->getFortranCompiler();
  }
  return QString();
}

QString FirstConfigure::getSystemVersion() const
{
  return this->mCrossCompilerSetupPage->getVersion();
}

QString FirstConfigure::getSystemProcessor() const
{
  return this->mCrossCompilerSetupPage->getProcessor();
}

QString FirstConfigure::getCrossRoot() const
{
  return this->mCrossCompilerSetupPage->getFindRoot();
}

QString const CrossModes[] = { "BOTH", "ONLY", "NEVER" };

QString FirstConfigure::getCrossProgramMode() const
{
  return CrossModes[this->mCrossCompilerSetupPage->getProgramMode()];
}

QString FirstConfigure::getCrossLibraryMode() const
{
  return CrossModes[this->mCrossCompilerSetupPage->getLibraryMode()];
}

QString FirstConfigure::getCrossIncludeMode() const
{
  return CrossModes[this->mCrossCompilerSetupPage->getIncludeMode()];
}
