/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef LAYOUT_STYLE_TYPEDOM_STYLEPROPERTYMAPREADONLY_H_
#define LAYOUT_STYLE_TYPEDOM_STYLEPROPERTYMAPREADONLY_H_

#include <stdint.h>

#include "js/TypeDecls.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/dom/CSSStyleValueBindingFwd.h"
#include "nsCOMPtr.h"
#include "nsISupports.h"
#include "nsISupportsImpl.h"
#include "nsStringFwd.h"
#include "nsTArrayForwardDeclare.h"
#include "nsWrapperCache.h"

class nsStyledElement;
template <class T>
class RefPtr;

namespace mozilla {

struct CSSPropertyId;
class ErrorResult;
struct StylePropertyTypedValueList;
struct URLExtraData;

namespace dom {

class CSSStyleRule;
class Element;
class OwningUndefinedOrCSSStyleValue;

class StylePropertyMapReadOnly : public nsISupports, public nsWrapperCache {
 public:
  explicit StylePropertyMapReadOnly(nsStyledElement* aStyledElement);

  explicit StylePropertyMapReadOnly(Element* aElement);

  explicit StylePropertyMapReadOnly(CSSStyleRule* aRule);

  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(StylePropertyMapReadOnly)

  nsISupports* GetParentObject() const;

  JSObject* WrapObject(JSContext*, JS::Handle<JSObject*> aGivenProto) override;

  // start of StylePropertyMapReadOnly Web IDL declarations

  // https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymapreadonly-get
  void Get(const nsACString& aProperty, OwningUndefinedOrCSSStyleValue& aRetVal,
           ErrorResult& aRv) const;

  // https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymapreadonly-getall
  void GetAll(const nsACString& aProperty,
              nsTArray<RefPtr<CSSStyleValue>>& aRetVal, ErrorResult& aRv) const;

  bool Has(const nsACString& aProperty, ErrorResult& aRv) const;

  uint32_t Size() const;

  uint32_t GetIterableLength() const;

  nsCString GetKeyAtIndex(uint32_t aIndex) const;

  nsTArray<RefPtr<CSSStyleValue>> GetValueAtIndex(uint32_t aIndex) const;

  // end of StylePropertyMapReadOnly Web IDL declarations

  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;

  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;

 protected:
  // Factored out code for various functions above.
  void GetAll(const CSSPropertyId&, nsTArray<RefPtr<CSSStyleValue>>& aRetVal,
              ErrorResult& aRv) const;

  virtual ~StylePropertyMapReadOnly() = default;

  class Declarations {
   public:
    enum class Kind : uint8_t {
      Inline,
      Computed,
      Rule,
    };
    explicit Declarations(nsStyledElement* aStyledElement)
        : mStyledElement(aStyledElement), mKind(Kind::Inline) {}

    explicit Declarations(Element* aElement)
        : mElement(aElement), mKind(Kind::Computed) {}

    explicit Declarations(CSSStyleRule* aRule)
        : mRule(aRule), mKind(Kind::Rule) {}

    StylePropertyTypedValueList GetAll(const CSSPropertyId& aPropertyId,
                                       ErrorResult& aRv) const;

    bool Has(const CSSPropertyId& aPropertyId) const;
    uint32_t Size() const;
    bool GetKeyAt(uint32_t aIndex, CSSPropertyId& aId) const;

    // Defined in StylePropertyMap.cpp
    void Set(const CSSPropertyId& aPropertyId, const nsACString& aValue,
             ErrorResult& aRv);

    URLExtraData* GetURLExtraData() const;
    void Unlink();

   private:
    union {
      nsStyledElement* mStyledElement;
      Element* mElement;
      CSSStyleRule* mRule;
    };
    const Kind mKind;
  };

  nsCOMPtr<nsISupports> mParent;
  Declarations mDeclarations;
};

}  // namespace dom
}  // namespace mozilla

#endif  // LAYOUT_STYLE_TYPEDOM_STYLEPROPERTYMAPREADONLY_H_
