// Copyright 2017 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "xfa/fxfa/parser/cxfa_validate.h"

#include "fxjs/xfa/cjx_node.h"
#include "fxjs/xfa/cjx_object.h"
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_message.h"
#include "xfa/fxfa/parser/cxfa_picture.h"
#include "xfa/fxfa/parser/cxfa_script.h"
#include "xfa/fxfa/parser/xfa_basic_data.h"

namespace {

const CXFA_Node::PropertyData kValidatePropertyData[] = {
    {XFA_Element::Message, 1, {}},
    {XFA_Element::Picture, 1, {}},
    {XFA_Element::Script, 1, {}},
    {XFA_Element::Extras, 1, {}},
};
const CXFA_Node::AttributeData kValidateAttributeData[] = {
    {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::ScriptTest, XFA_AttributeType::Enum,
     (void*)XFA_AttributeValue::Error},
    {XFA_Attribute::NullTest, XFA_AttributeType::Enum,
     (void*)XFA_AttributeValue::Disabled},
    {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::FormatTest, XFA_AttributeType::Enum,
     (void*)XFA_AttributeValue::Warning},
    {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0},
};

constexpr wchar_t kFormatTest[] = L"formatTest";
constexpr wchar_t kNullTest[] = L"nullTest";
constexpr wchar_t kScriptTest[] = L"scriptTest";

}  // namespace

CXFA_Validate::CXFA_Validate(CXFA_Document* doc, XFA_PacketType packet)
    : CXFA_Node(doc,
                packet,
                {XFA_XDPPACKET::kConfig, XFA_XDPPACKET::kTemplate,
                 XFA_XDPPACKET::kForm},
                XFA_ObjectType::ContentNode,
                XFA_Element::Validate,
                kValidatePropertyData,
                kValidateAttributeData,
                cppgc::MakeGarbageCollected<CJX_Node>(
                    doc->GetHeap()->GetAllocationHandle(),
                    this)) {}

CXFA_Validate::~CXFA_Validate() = default;

XFA_AttributeValue CXFA_Validate::GetFormatTest() {
  return JSObject()->GetEnum(XFA_Attribute::FormatTest);
}

void CXFA_Validate::SetNullTest(const WideString& wsValue) {
  absl::optional<XFA_AttributeValue> item =
      XFA_GetAttributeValueByName(wsValue.AsStringView());
  JSObject()->SetEnum(
      XFA_Attribute::NullTest,
      item.has_value() ? item.value() : XFA_AttributeValue::Disabled, false);
}

XFA_AttributeValue CXFA_Validate::GetNullTest() {
  return JSObject()->GetEnum(XFA_Attribute::NullTest);
}

XFA_AttributeValue CXFA_Validate::GetScriptTest() {
  return JSObject()->GetEnum(XFA_Attribute::ScriptTest);
}

WideString CXFA_Validate::GetMessageText(const WideString& wsMessageType) {
  CXFA_Message* pNode =
      JSObject()->GetProperty<CXFA_Message>(0, XFA_Element::Message);
  if (!pNode)
    return WideString();

  for (CXFA_Node* pItemNode = pNode->GetFirstChild(); pItemNode;
       pItemNode = pItemNode->GetNextSibling()) {
    if (pItemNode->GetElementType() != XFA_Element::Text)
      continue;

    WideString wsName = pItemNode->JSObject()->GetCData(XFA_Attribute::Name);
    if (wsName.IsEmpty() || wsName == wsMessageType)
      return pItemNode->JSObject()->GetContent(false);
  }
  return WideString();
}

void CXFA_Validate::SetFormatMessageText(const WideString& wsMessage) {
  SetMessageText(kFormatTest, wsMessage);
}

WideString CXFA_Validate::GetFormatMessageText() {
  return GetMessageText(kFormatTest);
}

void CXFA_Validate::SetNullMessageText(const WideString& wsMessage) {
  SetMessageText(kNullTest, wsMessage);
}

WideString CXFA_Validate::GetNullMessageText() {
  return GetMessageText(kNullTest);
}

WideString CXFA_Validate::GetScriptMessageText() {
  return GetMessageText(kScriptTest);
}

void CXFA_Validate::SetScriptMessageText(const WideString& wsMessage) {
  SetMessageText(kScriptTest, wsMessage);
}

void CXFA_Validate::SetMessageText(const WideString& wsMessageType,
                                   const WideString& wsMessage) {
  CXFA_Message* pNode =
      JSObject()->GetOrCreateProperty<CXFA_Message>(0, XFA_Element::Message);
  if (!pNode)
    return;

  for (CXFA_Node* pItemNode = pNode->GetFirstChild(); pItemNode;
       pItemNode = pItemNode->GetNextSibling()) {
    if (pItemNode->GetElementType() != XFA_Element::Text)
      continue;

    WideString wsName = pItemNode->JSObject()->GetCData(XFA_Attribute::Name);
    if (wsName.IsEmpty() || wsName == wsMessageType) {
      pItemNode->JSObject()->SetContent(wsMessage, wsMessage, false, false,
                                        true);
      return;
    }
  }

  CXFA_Node* pTextNode = pNode->CreateSamePacketNode(XFA_Element::Text);
  pNode->InsertChildAndNotify(pTextNode, nullptr);
  pTextNode->JSObject()->SetCData(XFA_Attribute::Name, wsMessageType);
  pTextNode->JSObject()->SetContent(wsMessage, wsMessage, false, false, true);
}

WideString CXFA_Validate::GetPicture() const {
  const auto* pNode = GetChild<CXFA_Picture>(0, XFA_Element::Picture, false);
  return pNode ? pNode->JSObject()->GetContent(false) : WideString();
}

CXFA_Script* CXFA_Validate::GetScriptIfExists() {
  return GetChild<CXFA_Script>(0, XFA_Element::Script, false);
}
