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

#include "SourcifySettingsDetails.h"
#include "DetailLayoutBuilder.h"
#include "DetailWidgetRow.h"
#include "Misc/EngineVersionComparison.h"
#include "Misc/MessageDialog.h"
#include "Sourcify.h"
#include "SourcifyCore.h"
#include "SourcifySettings.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Input/SEditableTextBox.h"
#include "Widgets/SBoxPanel.h"
#include "Widgets/Text/STextBlock.h"

#define LOCTEXT_NAMESPACE "SourcifySettingsDetails"

DEFINE_LOG_CATEGORY_STATIC(LogSourcifySettingsDetails, Log, All);

using namespace Sourcify;

namespace SourcifySettingsDetailsInternal
{
	void CustomizeCategoryForTrialMode(IDetailLayoutBuilder& DetailBuilder, FName Category, const FText& NewName)
	{
		const FText ToolTipText = LOCTEXT("PaidVersionToolTip", "This feature is only available in the paid version of Sourcify. Please visit https://codemongous.com for more information.");

		IDetailCategoryBuilder& CategoryBuilder = DetailBuilder.EditCategory(Category);
		CategoryBuilder.SetDisplayName(NewName);
#if !UE_VERSION_OLDER_THAN(5, 5, 0)
		CategoryBuilder.SetToolTip(ToolTipText);
#endif
	}
}

FSourcifySettingsDetails::FSourcifySettingsDetails() : SourcifyModule(FModuleManager::GetModuleChecked<FSourcifyModule>("Sourcify"))
{
}

TSharedRef<IDetailCustomization> FSourcifySettingsDetails::MakeInstance()
{
	return MakeShareable(new FSourcifySettingsDetails);
}

void FSourcifySettingsDetails::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
	TArray<TWeakObjectPtr<UObject>> ObjectsBeingCustomized;
	DetailBuilder.GetObjectsBeingCustomized(ObjectsBeingCustomized);
	check(ObjectsBeingCustomized.Num() == 1);

	static const FString HintString = TEXT("XXXX-XXXX-XXXX-XXXX");
	LicenseHolder = SourcifyModule.GetLicenseHolderInfo();
	
	UE_LOG(LogSourcifySettingsDetails, Display, TEXT("%s"), TEXT("FSourcifySettingsDetails instance created"));
	UE_LOG(LogSourcifySettingsDetails, Display, TEXT("License Status: %s"), SourcifyModule.GetLicenseStatus() == LicenseStatus::NoError ? TEXT("License is valid!") : *SourcifyModule.GetLicenseStatusMessage());
	LOG_LicenseHolder();
	
	IDetailCategoryBuilder& LicenseCategory = DetailBuilder.EditCategory("License");
	LicenseCategory.AddCustomRow(LOCTEXT("LicenseActivator", "LicenseActivator"))
	.NameContent()
	[
		SNew(SVerticalBox)
		+ SVerticalBox::Slot()
		.Padding(5)
		.AutoHeight()
		[
			SNew(STextBlock)
			.Text_Lambda([this]() { return FText::FromString(SourcifyModule.GetLicenseStatus() == LicenseStatus::NoError ? TEXT("License is valid!") : SourcifyModule.GetLicenseStatusMessage()); })
			.ColorAndOpacity_Lambda([this]() { return SourcifyModule.GetLicenseStatus() == LicenseStatus::NoError ? FLinearColor::Green : FLinearColor::Red; })
		]
		+ SVerticalBox::Slot()
		.Padding(5)
		.AutoHeight()
		[
			SNew(SBorder)
			.BorderImage(FAppStyle::GetNoBrush())
			.HAlign(HAlign_Fill)
			.Visibility_Lambda([this]() { return SourcifyModule.GetLicenseStatus() == LicenseStatus::NoError ? EVisibility::Visible : EVisibility::Collapsed; })
			[
				SNew(SVerticalBox)
				+ SVerticalBox::Slot()
				.Padding(5)
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text(LOCTEXT("SourceLicenseKeyText", "Key"))
					.ToolTipText(LOCTEXT("SourceLicenseKeyToolTip", "The Sourcify license key assigned to the current user."))
				]
				+ SVerticalBox::Slot()
				.Padding(5)
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text(LOCTEXT("SourceLicenseExpirationDateText", "Expiration Date"))
					.ToolTipText(LOCTEXT("SourceLicenseKeyToolTip", "The expiration date of the Sourcify key assigned to the current user."))
				]
				+ SVerticalBox::Slot()
				.Padding(5)
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text(LOCTEXT("SourceLicenseUserEmailText", "Email"))
					.ToolTipText(LOCTEXT("SourceLicenseKeyToolTip", "The email address of the current user."))
				]
				+ SVerticalBox::Slot()
				.Padding(5)
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text(LOCTEXT("SourceLicenseUserNameText", "Name"))
					.ToolTipText(LOCTEXT("SourceLicenseUserNameToolTip", "The name of the current user."))
				]
				+ SVerticalBox::Slot()
				.Padding(5)
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text(LOCTEXT("SourceLicenseUserCompanyText", "Company"))
					.ToolTipText(LOCTEXT("SourceLicenseUserCompanyToolTip", "The company of the current user."))
				]
			]
		]
	]
	.ValueContent()
	[
		SNew(SVerticalBox)
		+ SVerticalBox::Slot()
		.Padding(5)
		.AutoHeight()
		[
			SAssignNew(LicenseKeyBox, SEditableTextBox)
			.HintText(FText::FromString(HintString))
			.OnTextChanged_Lambda([this](const FText& Text) { LicenseReadyToVerify = Text.ToString().TrimStartAndEnd().Len() == HintString.Len(); })
			.Visibility_Lambda([this]() { return SourcifyModule.GetLicenseStatus() == LicenseStatus::Error ? EVisibility::Visible : EVisibility::Collapsed; })
		]
		+ SVerticalBox::Slot()
		.Padding(5)
		.AutoHeight()
		[
			SNew(SButton)
			.Text_Lambda([this]() { return FText::FromString(SourcifyModule.GetLicenseStatus() == LicenseStatus::NoError ? TEXT("Deactivate Current License") : TEXT("Activate License")); })
			.ToolTipText_Lambda([this]()
				{
					return FText::FromString(SourcifyModule.GetLicenseStatus() == LicenseStatus::NoError ?
						TEXT("Deactivate the current license. Click this to enter a new license.") :
						TEXT("Activate a new license. Enter a valid license into the text field below then click this."));
				})
			.OnClicked_Lambda([this]()
				{
					if (!SourcifyModule.IsLicenseActionAllowed())
					{
						return FReply::Handled();
					}

					// Button is in "Activate license" state
					if (SourcifyModule.GetLicenseStatus() == LicenseStatus::Error && LicenseReadyToVerify)
					{
						if (SourcifyModule.ActivateLicense(LicenseKeyBox->GetText().ToString()) == LicenseStatus::NoError)
						{
							UE_LOG(LogSourcifySettingsDetails, Display, TEXT("%s"), TEXT("License activated successfully."));
							if (SourcifyModule.CheckLicense() == LicenseStatus::Error)
							{
								UE_LOG(LogSourcifySettingsDetails, Error, TEXT("Error in license manager after successful activation: %s"), *SourcifyModule.GetLicenseStatusMessage());
							}
							LicenseHolder = SourcifyModule.GetLicenseHolderInfo();
							LOG_LicenseHolder();
						}
					}
					// Button is in "Deactivate current license" state
					else if (SourcifyModule.GetLicenseStatus() == LicenseStatus::NoError)
					{
						// Prompt user for confirmation before deactivating
						EAppReturnType::Type UserResponse =
							FMessageDialog::Open(EAppMsgType::YesNo,
												 LOCTEXT("DeactivateLicenseMessage", "Are you sure you want to deactivate the current license? You will need to enter a valid license key to continue using the paid features."),
												 LOCTEXT("DeactivateLicenseTitle", "Deactivate License"));
						if (UserResponse == EAppReturnType::Yes)
						{
							if (SourcifyModule.DeactivateCurrentLicense() == LicenseStatus::NoError)
							{
								UE_LOG(LogSourcifySettingsDetails, Display, TEXT("%s"), TEXT("License deactivated successfully."));
								// Check the license to refresh UI info
								SourcifyModule.CheckLicense();
							}
						}
					}

					return FReply::Handled();
				})
			.IsEnabled_Lambda([this]()
				{
					if (SourcifyModule.IsLicenseActionAllowed())
					{
						// Button is in "Activate license" state
						if (SourcifyModule.GetLicenseStatus() == LicenseStatus::Error && LicenseReadyToVerify)
						{
							return true;
						}
						// Button is in "Deactivate current license" state
						else if (SourcifyModule.GetLicenseStatus() == LicenseStatus::NoError)
						{
							return true;
						}
					}

					return false;
				})
		]
		+ SVerticalBox::Slot()
		.Padding(5)
		.AutoHeight()
		[
			SNew(SBorder)
			.BorderImage(FAppStyle::GetNoBrush())
			.HAlign(HAlign_Fill)
			.Visibility_Lambda([this]() { return SourcifyModule.GetLicenseStatus() == LicenseStatus::NoError ? EVisibility::Visible : EVisibility::Collapsed; })
			[
				SNew(SVerticalBox)
				+ SVerticalBox::Slot()
				.Padding(5)
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text_Lambda([this]() 
						{
							FString LicenseKey = LicenseHolder.LicenseKey.c_str();
							FString ObfuscatedLicenseKey = LicenseKey.Left(4) + FString::ChrN(LicenseKey.Len() - 4, TEXT('*'));

							return FText::FromString(ObfuscatedLicenseKey); 
						})
					.ToolTipText(LOCTEXT("SourceLicenseKeyValueToolTip", "The Sourcify license key assigned to the current user."))
				]
				+ SVerticalBox::Slot()
				.Padding(5)
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text_Lambda([this]() { return FText::FromString(LicenseHolder.LicenseExpirationDate.c_str()); })
					.ToolTipText(LOCTEXT("SourceLicenseExpirationValueToolTip", "The expiration date of the Sourcify key assigned to the current user."))
				]
				+ SVerticalBox::Slot()
				.Padding(5)
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text_Lambda([this]() { return FText::FromString(LicenseHolder.Email.c_str()); })
					.ToolTipText(LOCTEXT("SourceLicenseUserEmailToolTip", "The email address of the current user."))
				]
				+ SVerticalBox::Slot()
				.Padding(5)
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text_Lambda([this]() { return FText::FromString((LicenseHolder.FirstName + TEXT(" ") + LicenseHolder.LastName).c_str()); })
					.ToolTipText(LOCTEXT("SourceLicenseUserNameValueToolTip", "The name of the current user."))
				]
				+ SVerticalBox::Slot()
				.Padding(5)
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text_Lambda([this]() { return FText::FromString(LicenseHolder.Company.c_str()); })
					.ToolTipText(LOCTEXT("SourceLicenseCompanyValueToolTip", "The company of the current user."))
				]
			]
		]
	];

	if (SourcifyModule.GetLicenseStatus() != LicenseStatus::NoError)
	{
		SourcifySettingsDetailsInternal::CustomizeCategoryForTrialMode(DetailBuilder, "Delegates", LOCTEXT("DelegatesPaidVersion", "Delegates (paid version only)"));
		SourcifySettingsDetailsInternal::CustomizeCategoryForTrialMode(DetailBuilder, "Indentation", LOCTEXT("IndentationPaidVersion", "Indentation (paid version only)"));
		SourcifySettingsDetailsInternal::CustomizeCategoryForTrialMode(DetailBuilder, "Spacing", LOCTEXT("SpacingPaidVersion", "Spacing (paid version only)"));
		SourcifySettingsDetailsInternal::CustomizeCategoryForTrialMode(DetailBuilder, "Properties and Fields", LOCTEXT("PropertiesandFieldsPaidVersion", "Properties and Fields (paid version only)"));
		SourcifySettingsDetailsInternal::CustomizeCategoryForTrialMode(DetailBuilder, "Tool Tips", LOCTEXT("ToolTipsPaidVersion", "Tool Tips (paid version only)"));
	}
}

void FSourcifySettingsDetails::LOG_LicenseHolder()
{
	UE_LOG(LogSourcifySettingsDetails, Display, TEXT("License Holder First Name: %s"), LicenseHolder.FirstName.c_str());
	UE_LOG(LogSourcifySettingsDetails, Display, TEXT("License Holder Last Name: %s"), LicenseHolder.LastName.c_str());
	UE_LOG(LogSourcifySettingsDetails, Display, TEXT("License Holder Email: %s"), LicenseHolder.Email.c_str());
	UE_LOG(LogSourcifySettingsDetails, Display, TEXT("License Holder Company: %s"), LicenseHolder.Company.c_str());
}

#undef LOCTEXT_NAMESPACE
