enum ERentStatus
{
	PAID = 0,
	OVERDUE = 1,
	EVICTED = 2,
}

enum EPaymentSchedule
{
	WEEKLY = 0,
	MONTHLY = 1,
}

class SetApartmentScreenStatusEvent extends Event
{
	editable var m_rentStatus : ERentStatus;

	public constexpr function GetFriendlyDescription() : String
	{
		return "Set Apartment Screen Status";
	}

}

class SetApartmentScreenMessageEvent extends Event
{
	[ customEditor = "TweakDBGroupInheritance;ScreenMessageData" ]
	editable var m_messageRecordID : TweakDBID;
	editable var m_targetRentStatus : ERentStatus;

	public constexpr function GetFriendlyDescription() : String
	{
		return "Set Message Record";
	}

}

class ApartmentScreenController extends LcdScreenController
{

	public const override function GetPS() : ApartmentScreenControllerPS
	{
		return ( ( ApartmentScreenControllerPS )( GetBasePS() ) );
	}

}

class ApartmentScreenControllerPS extends LcdScreenControllerPS
{
	default m_deviceName = "LocKey#193";
	default m_tweakDBRecord = T"Devices.LcdScreen";
	default m_tweakDBDescriptionRecord = T"device_descriptions.LcdScreen";
	default m_hasAuthorizationModule = true;
	[ category = "UI" ]
	private instanceeditable var m_initialRentStatus : ERentStatus;
	[ category = "UI" ][ customEditor = "TweakDBGroupInheritance;ScreenMessageData" ]
	private instanceeditable editable var m_overdueMessageRecordID : TweakDBID;
	[ category = "UI" ][ customEditor = "TweakDBGroupInheritance;ScreenMessageData" ]
	private instanceeditable editable var m_paidMessageRecordID : TweakDBID;
	[ category = "UI" ][ customEditor = "TweakDBGroupInheritance;ScreenMessageData" ]
	private instanceeditable editable var m_evictionMessageRecordID : TweakDBID;
	[ category = "UI" ]
	private instanceeditable var m_paymentSchedule : EPaymentSchedule;
	default m_paymentSchedule = EPaymentSchedule.WEEKLY;
	[ category = "UI" ]
	private instanceeditable var m_showOverdueValue : Bool;
	default m_showOverdueValue = true;
	[ category = "UI" ]
	private instanceeditable var m_randomizeInitialOverdue : Bool;
	default m_randomizeInitialOverdue = true;
	[ category = "UI" ][ rangeMin = "0" ][ rangeMax = "90" ]
	private instanceeditable var m_initialOverdue : Int32;
	[ category = "UI" ]
	private instanceeditable var m_allowAutomaticRentStatusChange : Bool;
	default m_allowAutomaticRentStatusChange = true;
	private const var m_maxDays : Int32;
	default m_maxDays = 90;
	private persistent var m_currentOverdue : Int32;
	private persistent var m_isInitialRentStateSet : Bool;
	private persistent var m_currentRentStatus : ERentStatus;
	private persistent var m_lastStatusChangeDay : Int32;

	protected event OnInstantiated()
	{
		super.OnInstantiated();
		if( !( IsStringValid( m_deviceName ) ) )
		{
			m_deviceName = "Gameplay-Devices-DisplayNames-Screen";
		}
	}

	protected override function GameAttached()
	{
		UpdateRentState();
	}

	public override function GetQuestActions( out outActions : array< DeviceAction >, const context : ref< GetActionsContext > )
	{
		super.GetQuestActions( outActions, context );
	}

	public function UpdateRentState()
	{
		if( !( m_isInitialRentStateSet ) )
		{
			InitializeRentState();
		}
		else
		{
			if( m_allowAutomaticRentStatusChange )
			{
				ReEvaluateRentStatus();
			}
			if( m_currentRentStatus == ERentStatus.OVERDUE )
			{
				UpdateCurrentOverdue();
			}
		}
		RefreshUI( GetBlackboard() );
	}

	private function InitializeRentState()
	{
		m_currentOverdue = GetInitialOverdueValue();
		if( m_allowAutomaticRentStatusChange )
		{
			if( m_currentOverdue > 0 )
			{
				SetCurrentRentStatus( ERentStatus.OVERDUE );
			}
			else
			{
				SetCurrentRentStatus( ERentStatus.PAID );
			}
		}
		else
		{
			SetCurrentRentStatus( m_initialRentStatus );
		}
		m_isInitialRentStateSet = true;
	}

	private function GetInitialOverdueValue() : Int32
	{
		var returnValue : Int32;
		var randValue : Int32;
		randValue = RandRange( 0, 2 );
		if( m_randomizeInitialOverdue && ( randValue == 1 ) )
		{
			returnValue = RandRange( 0, m_maxDays );
		}
		else
		{
			if( m_initialRentStatus == ERentStatus.OVERDUE )
			{
				m_initialOverdue = 1;
			}
			returnValue = m_initialOverdue;
		}
		return returnValue;
	}

	private function SetCurrentRentStatus( status : ERentStatus )
	{
		var messageID : TweakDBID;
		m_currentRentStatus = status;
		m_lastStatusChangeDay = GetCurrentDay();
		if( m_currentRentStatus == ERentStatus.PAID )
		{
			m_currentOverdue = 0;
			if( TDBID.IsValid( m_paidMessageRecordID ) )
			{
				messageID = m_paidMessageRecordID;
			}
			else
			{
				messageID = T"screen_messages.RentPaid";
			}
		}
		else if( m_currentRentStatus == ERentStatus.OVERDUE )
		{
			if( TDBID.IsValid( m_overdueMessageRecordID ) )
			{
				messageID = m_overdueMessageRecordID;
			}
			else
			{
				messageID = T"screen_messages.RentOverdue";
			}
		}
		else if( m_currentRentStatus == ERentStatus.EVICTED )
		{
			if( TDBID.IsValid( m_evictionMessageRecordID ) )
			{
				messageID = m_evictionMessageRecordID;
			}
			else
			{
				messageID = T"screen_messages.EvictionNotice";
			}
		}
		SetMessageRecordID( messageID );
	}

	private function UpdateCurrentOverdue()
	{
		m_currentOverdue += 1;
	}

	private function GetGameTime() : GameTime
	{
		return GameInstance.GetTimeSystem( GetGameInstance() ).GetGameTime();
	}

	private function GetCurrentDay() : Int32
	{
		return GameTime.Days( GetGameTime() );
	}

	private function GetDaysPassed() : Int32
	{
		return GetCurrentDay() - m_lastStatusChangeDay;
	}

	private function ReEvaluateRentStatus()
	{
		var randValue : Int32;
		var stateChangeProbablity : Int32;
		if( m_currentRentStatus == ERentStatus.PAID && ( GetDaysPassed() < GetPaymentScheduleValue() ) )
		{
			return;
		}
		stateChangeProbablity = GetStateChangeProbabilityValue();
		randValue = RandRange( 0, 100 );
		if( randValue > stateChangeProbablity )
		{
			return;
		}
		if( m_currentRentStatus == ERentStatus.OVERDUE )
		{
			randValue = RandRange( 0, 2 );
			if( randValue == 0 )
			{
				SetCurrentRentStatus( ERentStatus.PAID );
			}
			else
			{
				SetCurrentRentStatus( ERentStatus.EVICTED );
			}
		}
		else if( m_currentRentStatus == ERentStatus.PAID )
		{
			SetCurrentRentStatus( ERentStatus.OVERDUE );
		}
		else if( m_currentRentStatus == ERentStatus.EVICTED )
		{
			SetCurrentRentStatus( ERentStatus.PAID );
		}
	}

	private function GetStateChangeProbabilityValue() : Int32
	{
		var daysPassed : Float;
		var returnValue : Float;
		if( m_currentRentStatus == ERentStatus.OVERDUE )
		{
			daysPassed = ( ( Float )( m_currentOverdue ) );
		}
		else
		{
			daysPassed = ( ( Float )( GetCurrentDay() ) ) - ( ( Float )( m_lastStatusChangeDay ) );
		}
		if( daysPassed > ( ( Float )( m_maxDays ) ) )
		{
			returnValue = 100.0;
		}
		else
		{
			returnValue = ( daysPassed / ( ( Float )( m_maxDays ) ) ) * 100.0;
		}
		return ( ( Int32 )( returnValue ) );
	}

	public const function GetCurrentRentStatus() : ERentStatus
	{
		return m_currentRentStatus;
	}

	public const function ShouldShowOverdueValue() : Bool
	{
		return m_showOverdueValue;
	}

	public const function GetCurrentOverdueValue() : Int32
	{
		return m_currentOverdue;
	}

	public const function GetPaymentScheduleValue() : Int32
	{
		var returnValue : Int32;
		if( m_paymentSchedule == EPaymentSchedule.WEEKLY )
		{
			returnValue = 7;
		}
		else if( m_paymentSchedule == EPaymentSchedule.MONTHLY )
		{
			returnValue = 30;
		}
		return returnValue;
	}

	private function OnSetApartmentScreenStatusEvent( evt : SetApartmentScreenStatusEvent ) : EntityNotificationType
	{
		SetCurrentRentStatus( evt.m_rentStatus );
		UpdateRentState();
		return EntityNotificationType.DoNotNotifyEntity;
	}

	private function OnSetApartmentScreenMessageEvent( evt : SetApartmentScreenMessageEvent ) : EntityNotificationType
	{
		if( evt.m_targetRentStatus == ERentStatus.OVERDUE )
		{
			m_overdueMessageRecordID = evt.m_messageRecordID;
		}
		else if( evt.m_targetRentStatus == ERentStatus.PAID )
		{
			m_paidMessageRecordID = evt.m_messageRecordID;
		}
		else if( evt.m_targetRentStatus == ERentStatus.EVICTED )
		{
			m_evictionMessageRecordID = evt.m_messageRecordID;
		}
		SetMessageRecordID( evt.m_messageRecordID );
		UpdateRentState();
		return EntityNotificationType.DoNotNotifyEntity;
	}

}

