ILauncherProfilePtr FLauncherProfileManager::LoadJSONProfile(FString ProfileFile)
{
	FLauncherProfile* Profile = new FLauncherProfile(AsShared());

	FString FileContents;
	if (!FFileHelper::LoadFileToString(FileContents, *ProfileFile))
	{
		return nullptr;
	}

	TSharedPtr<FJsonObject> Object;
	TSharedRef<TJsonReader<> > Reader = TJsonReaderFactory<>::Create(FileContents);
	if (!FJsonSerializer::Deserialize(Reader, Object) || !Object.IsValid())
	{
		return nullptr;
	}

	if (Profile->Load(*(Object.Get())))
	{
		ILauncherDeviceGroupPtr DeviceGroup = GetDeviceGroup(Profile->GetDeployedDeviceGroupId());
		if (!DeviceGroup.IsValid())
		{
			DeviceGroup = AddNewDeviceGroup();
		}
		Profile->SetDeployedDeviceGroup(DeviceGroup);

		return MakeShareable(Profile);
	}

	return nullptr;
}
FText SProjectLauncherDeviceGroupSelector::HandleDeviceGroupComboBoxWidgetText(ILauncherDeviceGroupPtr Group) const
{
	if (Group.IsValid())
	{
		return FText::FromString(Group->GetName());
	}

	return FText::GetEmpty();
}
FString SProjectLauncherDeviceGroupSelector::HandleDeviceGroupComboBoxGetEditableText()
{
	ILauncherDeviceGroupPtr SelectedGroup = DeviceGroupComboBox->GetSelectedItem();

	if (SelectedGroup.IsValid())
	{
		return SelectedGroup->GetName();
	}

	return FString();
}
FText SProjectLauncherDeviceGroupSelector::HandleDeviceGroupComboBoxContent() const
{
	ILauncherDeviceGroupPtr SelectedGroup = DeviceGroupComboBox->GetSelectedItem();

	if (SelectedGroup.IsValid())
	{
		return FText::FromString(SelectedGroup->GetName());
	}

	return LOCTEXT("CreateOrSelectGroupText", "Create or select a device group...");
}
void SProjectLauncherDeviceGroupSelector::SetSelectedGroup(const ILauncherDeviceGroupPtr& DeviceGroup)
{
	if (!DeviceGroup.IsValid() || ProfileManager->GetAllDeviceGroups().Contains(DeviceGroup))
	{
		DeviceGroupComboBox->SetSelectedItem(DeviceGroup);
	}
}
ILauncherProfilePtr FLauncherProfileManager::LoadProfile( FArchive& Archive )
{
	FLauncherProfile* Profile = new FLauncherProfile(AsShared());

	if (Profile->Serialize(Archive))
	{
		ILauncherDeviceGroupPtr DeviceGroup = GetDeviceGroup(Profile->GetDeployedDeviceGroupId());
		if (!DeviceGroup.IsValid())
		{
			DeviceGroup = AddNewDeviceGroup();	
		}
		Profile->SetDeployedDeviceGroup(DeviceGroup);

		return MakeShareable(Profile);
	}

	return nullptr;
}
void FLauncherProfileManager::AddDeviceGroup( const ILauncherDeviceGroupRef& DeviceGroup )
{
	if (!DeviceGroups.Contains(DeviceGroup))
	{
		// replace the existing device group
		ILauncherDeviceGroupPtr ExistingGroup = GetDeviceGroup(DeviceGroup->GetId());

		if (ExistingGroup.IsValid())
		{
			RemoveDeviceGroup(ExistingGroup.ToSharedRef());
		}

		// add the new device group
		DeviceGroups.Add(DeviceGroup);
		SaveDeviceGroups();

		DeviceGroupAddedDelegate.Broadcast(DeviceGroup);
	}
}
FReply SProjectLauncherDeviceGroupSelector::HandleDeviceGroupComboBoxRemoveClicked()
{
	ILauncherDeviceGroupPtr SelectedGroup = DeviceGroupComboBox->GetSelectedItem();

	if (SelectedGroup.IsValid())
	{
		ProfileManager->RemoveDeviceGroup(SelectedGroup.ToSharedRef());
	}

	if (ProfileManager->GetAllDeviceGroups().Num() > 0)
	{
		DeviceGroupComboBox->SetSelectedItem(ProfileManager->GetAllDeviceGroups()[0]);
	}
	else
	{
		DeviceGroupComboBox->SetSelectedItem(NULL);
	}

	return FReply::Handled();
}
void FLauncherAutomatedServiceProvider::SetupProfileAndGroupSettings( const TCHAR* Params )
{
	bool bHasValidProfile = false;
	bool bHasValidDeviceGroup = false;

	ILauncherServicesModule& LauncherServicesModule = FModuleManager::LoadModuleChecked<ILauncherServicesModule>(TEXT( "LauncherServices"));

	ProfileManager = LauncherServicesModule.GetProfileManager();

	if( ProfileManager.IsValid() )
	{
		FString ProfileName;
		if( FParse::Value( Params, TEXT( "Profile=" ), ProfileName ) )
		{
			AutomatedProfile = ProfileManager->FindProfile(ProfileName);

			bHasValidProfile = AutomatedProfile.IsValid() && AutomatedProfile->IsValidForLaunch();
		}

		if( !AutomatedProfile.IsValid() )
		{
			AutomatedProfile = LauncherServicesModule.CreateProfile(TEXT("LauncherAutomatedServiceProviderProfile"));
			bShouldDeleteProfileWhenComplete = true;

			UE_LOG(LauncherAutomatedService, Display, TEXT("PROFILE:") );

			// Get the game name, this must exist here 
			FString ProfileGameName;
			
			bool bHasValidGameName = FParse::Value( Params, TEXT( "GameName=" ), ProfileGameName );

			if( bHasValidGameName )
			{
				// @todo gmp: fix automated service provider; must use project path here
				// game names are no longer supported
				//AutomatedProfile->SetLegacyGameName(ProfileGameName);

				UE_LOG(LauncherAutomatedService, Display, TEXT("---Game: %s"), *ProfileGameName);
			}
			else
			{
				UE_LOG(LauncherAutomatedService, Error, TEXT("A valid game name was not found on the commandline") );
			}


			// Get the game config, this must exist here
			FString ProfileGameConfig;

			bool bHasValidConfig = FParse::Value( Params, TEXT( "Config=" ), ProfileGameConfig );
			
			if( bHasValidConfig )
			{
				AutomatedProfile->SetBuildConfiguration(EBuildConfigurations::FromString(ProfileGameConfig));

				UE_LOG(LauncherAutomatedService, Display, TEXT("---Config: %s"), *ProfileGameConfig);
			}
			else
			{
				UE_LOG(LauncherAutomatedService, Error, TEXT("A valid game configuration was not found on the commandline") );
			}
			
			// Must have a valid game name and config to be able to launch
			bHasValidProfile = AutomatedProfile->IsValidForLaunch();

			if( bHasValidProfile )
			{
				// Get the map name, this is optional
				FString ProfileMapName;
				
				FParse::Value( Params, TEXT( "Map=" ), ProfileMapName );
				
				if( FParse::Value( Params, TEXT( "Map=" ), ProfileMapName ) )
				{
					AutomatedProfile->GetDefaultLaunchRole()->SetInitialMap(ProfileMapName);

					UE_LOG(LauncherAutomatedService, Display, TEXT("%s"), *FText::Format(FText::FromString("---Map: {0}"), FText::FromString(ProfileMapName)).ToString());
				}

				// Get the command line, this is optional
				FString ProfileCmdLine;
				
				FParse::Value( Params, TEXT( "CmdLine=" ), ProfileCmdLine );
				
				if( !ProfileMapName.IsEmpty() )
				{
					AutomatedProfile->GetDefaultLaunchRole()->SetCommandLine(ProfileCmdLine);

					UE_LOG(LauncherAutomatedService, Display, TEXT("%s"), *FText::Format(FText::FromString("---CmdLine: {0}"), FText::FromString(ProfileCmdLine)).ToString());
				}
			}
		}
	}

	if( bHasValidProfile )
	{
		// Get the device group we will be deploying to
		FString DeviceGroupName;

		if( FParse::Value( Params, TEXT( "DeviceGroup=" ), DeviceGroupName ) )
		{
			AutomatedDeviceGroup = NULL;
			TArray< ILauncherDeviceGroupPtr > DeviceGroups = ProfileManager->GetAllDeviceGroups();

			for( int32 DeviceGroupIdx = 0; DeviceGroupIdx < DeviceGroups.Num(); DeviceGroupIdx++ )
			{
				ILauncherDeviceGroupPtr CurrentGroup = DeviceGroups[ DeviceGroupIdx ];

				if( CurrentGroup->GetName() == DeviceGroupName )
				{
					AutomatedDeviceGroup = CurrentGroup;
					break;
				}
			}

			bHasValidDeviceGroup = AutomatedDeviceGroup.IsValid() && (AutomatedDeviceGroup->GetNumDevices() > 0);

			// A reference to the proxy manager responsible for device activity here.
			DeviceProxyManager = FModuleManager::LoadModuleChecked<ITargetDeviceServicesModule>(TEXT("TargetDeviceServices")).GetDeviceProxyManager();
			DeviceProxyManager->OnProxyAdded().AddRaw( this, &FLauncherAutomatedServiceProvider::HandleDeviceProxyManagerProxyAdded );

			LastDevicePingTime = FPlatformTime::Seconds();
		}
	}

	bHasErrors = ( bHasValidProfile == false || bHasValidDeviceGroup == false ); 
}