#include "stdafx.h"

#include "xtr/ExteorOptions.h"
#include "xtr/doc/RSModelDoc.h"
#include "xtr/io/RSMLegacyLoader.h"
#include "xtr/dialog/NewDocument.h"

using ccl::semantic::RSModel;

namespace xtr::doc {

#pragma warning( push )
#pragma warning( disable : 26440 26436 26454 )

IMPLEMENT_DYNCREATE(RSModelDoc, SelectableDoc)

#pragma warning( pop )

RSModelDoc::RSModelDoc() {
  model.AddObserver(*this);
}

RSModelDoc::~RSModelDoc() {
  model.RemoveObserver(*this);
}

void RSModelDoc::Serialize(CArchive& ar) {
  MFCSerializable<RSMVersion>::Serialize(ar);
}

void RSModelDoc::OnObserve(const ccl::types::Message& change) {
  if (const auto* changePtr = dynamic_cast<const ccl::change::ModMessage*>(&change); changePtr != nullptr) {
    SetModifiedFlag(TRUE);
  }
}

BOOL RSModelDoc::OnNewDocument() {
  if (XTROptions::App().IsSilent()) {
    return CDocument::OnNewDocument();
  } else if (dialog::NewRSForm dialog(this->GetTitle()); dialog.DoModal() != IDOK) {
    return FALSE;
  } else {
    model.title = mfc::ToSTL(dialog.newAlias);
    model.alias = mfc::ToSTL(dialog.newTitle);
    return TRUE;
  }
}

BOOL RSModelDoc::OnOpenDocument(LPCTSTR path) {
  if (CString(path).Right(4).MakeLower() != ExtensionFor(FileType::rsm)) {
    return FALSE;
  } 
  if (!LoadJSON(mfc::ToUTF8(path))
      && !CDocument::OnOpenDocument(path)) {
    return FALSE;
  }
  SetPathName(path, FALSE);
  return TRUE;
}

BOOL RSModelDoc::OnSaveDocument(LPCTSTR path) {
  if (!SaveJSON(mfc::ToUTF8(path))) {
    return FALSE;
  }
  SetPathName(path, FALSE);
  SetModifiedFlag(FALSE);
  return TRUE;
}

JSON RSModelDoc::ExtractData() const {
  auto result = JSON(model);
  result["selection"] = selection;
  return result;
}

bool RSModelDoc::LoadData(const JSON& object) {
  [[maybe_unused]] const auto noObserving = DndGuard();
  object.get_to(model);
  SetSelection(object.at("selection").get<SetOfEntities>());
  return true;
}

bool RSModelDoc::LegacyLoad(io::CArchiveAdapter& archive) {
  const auto guard = DndGuard();
  auto loader = io::RSMLegacyLoader{ archive, model };
  loader.LoadVersion();
  loader.DoLoad();
  SetSelection(loader.selection);
  return true;
}

} // namespace xtr::doc