// Copyright (c) 2024 Codemongous LLC. All Rights Reserved.

#pragma once

#include "ISCW_FProperty.h"
#include "ISCW_UObject.h"
#include "ISCW_UPackage.h"
#include "SCW_Base.h"
#include <string>
#include "UObject/Object.h"
#include "UObject/StrongObjectPtr.h"
#include "UObject/WeakObjectPtr.h"
#include <variant>

using std::shared_ptr;
using std::variant;
using std::wstring;

#pragma warning(disable: 4250)

namespace Sourcify
{
	class SCW_UObject : public SCW_Base, public virtual ISCW_UObject
	{
	public:

		SCW_UObject(UObject* InObject);

		shared_ptr<ISCW_UObject> GetArchetype() const override;

		void GetArchetypeInstances(vector<shared_ptr<ISCW_UObject>>& OutArchetypeInstances) const override;

		shared_ptr<class ISCW_UClass> GetClass() const override;

		void GetDefaultSubobjects(vector<ISCW_UObjectPtr>& OutDefaultSubobjects) const override;

		ISCW_UPackagePtr GetExternalPackage() const override;

		SCW_EObjectFlags GetFlags() const override;

		wstring GetName() const override;

		ISCW_UPackagePtr GetPackage() const override;

		wstring GetPathName() const override;

		ISCW_UObjectPtr GetOuter() const override;

		ISCW_UObjectPtr GetOutermostObject() const override;

		bool HasAllFlags(SCW_EObjectFlags FlagsToCheck) const override;

		bool HasAnyFlags(SCW_EObjectFlags FlagsToCheck) const override;

		bool IsDefaultSubobject() const override;

		bool IsEditorOnly() const override;
		
		bool IsNative() const override;

		bool MarkPackageDirty() const override;

		void Modify(bool bAlwaysMarkDirty) override;

		void PostEditChangeProperty(ISCW_FPropertyPtr InProperty, SCW_EPropertyChangeType InChangeType = SCW_EPropertyChangeType::Unspecified) override;
		
		void PreEditChange(ISCW_FPropertyPtr PropertyAboutToChange) override;

		void PostReinitProperties() override;

		bool Rename(const wchar_t* NewName = nullptr, shared_ptr<ISCW_UObject> NewOuter = nullptr, SCW_ERenameFlags Flags = SCW_ERenameFlags::EREN_None) override;

		void SetFlags(SCW_EObjectFlags FlagsToSet) override;

		bool ISCW_Equals(const ISCW_UObject& Other) const override;

		bool ISCW_Equals(const shared_ptr<const ISCW_UObject> Other) const override;

		size_t ISCW_GetHash() const override;

		bool Less(const ISCW_UObject& Other) const override;

		void MakeInternalStrongObjectPointer() override;

		ISCW_UObjectPtr ToUObjectPtr() override;

		ISCW_UObjectConstPtr ToUObjectPtr() const override;

		UObject* ToUObjectRawPtr() const;

	protected:
		UObject* GetInternalObject() const;

	private:
		variant<TStrongObjectPtr<UObject>, TWeakObjectPtr<UObject>> Object;
	};
} // namespace Sourcify