/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#include "cmCursesCacheEntryComposite.h"

#include <cassert>
#include <utility>
#include <vector>

#include <cm/memory>

#include "cmCursesBoolWidget.h"
#include "cmCursesFilePathWidget.h"
#include "cmCursesLabelWidget.h"
#include "cmCursesOptionsWidget.h"
#include "cmCursesPathWidget.h"
#include "cmCursesStringWidget.h"
#include "cmCursesWidget.h"
#include "cmList.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmValue.h"

cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
  std::string const& key, int labelwidth, int entrywidth)
  : Key(key)
  , LabelWidth(labelwidth)
  , EntryWidth(entrywidth)
{
  this->Label =
    cm::make_unique<cmCursesLabelWidget>(this->LabelWidth, 1, 1, 1, key);
  this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(3, 1, 1, 1, "   ");
  this->Entry =
    cm::make_unique<cmCursesStringWidget>(this->EntryWidth, 1, 1, 1);
}

cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
  std::string const& key, cmState* state, bool isNew, int labelwidth,
  int entrywidth)
  : Key(key)
  , LabelWidth(labelwidth)
  , EntryWidth(entrywidth)
{
  this->Label =
    cm::make_unique<cmCursesLabelWidget>(this->LabelWidth, 1, 1, 1, key);
  if (isNew) {
    this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(3, 1, 1, 1, " * ");
  } else {
    this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(3, 1, 1, 1, "   ");
  }

  cmValue value = state->GetCacheEntryValue(key);
  assert(value);
  switch (state->GetCacheEntryType(key)) {
    case cmStateEnums::BOOL: {
      auto bw = cm::make_unique<cmCursesBoolWidget>(this->EntryWidth, 1, 1, 1);
      bw->SetValueAsBool(value.IsOn());
      this->Entry = std::move(bw);
      break;
    }
    case cmStateEnums::PATH: {
      auto pw = cm::make_unique<cmCursesPathWidget>(this->EntryWidth, 1, 1, 1);
      pw->SetString(*value);
      this->Entry = std::move(pw);
      break;
    }
    case cmStateEnums::FILEPATH: {
      auto fpw =
        cm::make_unique<cmCursesFilePathWidget>(this->EntryWidth, 1, 1, 1);
      fpw->SetString(*value);
      this->Entry = std::move(fpw);
      break;
    }
    case cmStateEnums::STRING: {
      cmValue stringsProp = state->GetCacheEntryProperty(key, "STRINGS");
      if (stringsProp) {
        auto ow =
          cm::make_unique<cmCursesOptionsWidget>(this->EntryWidth, 1, 1, 1);
        for (auto const& opt : cmList{ *stringsProp }) {
          ow->AddOption(opt);
        }
        ow->SetOption(*value);
        this->Entry = std::move(ow);
      } else {
        auto sw =
          cm::make_unique<cmCursesStringWidget>(this->EntryWidth, 1, 1, 1);
        sw->SetString(*value);
        this->Entry = std::move(sw);
      }
      break;
    }
    case cmStateEnums::UNINITIALIZED:
      cmSystemTools::Error("Found an undefined variable: " + key);
      break;
    default:
      // TODO : put warning message here
      break;
  }
}

cmCursesCacheEntryComposite::~cmCursesCacheEntryComposite() = default;

char const* cmCursesCacheEntryComposite::GetValue()
{
  if (this->Label) {
    return this->Label->GetValue();
  }
  return nullptr;
}
