1+ using System ;
2+ using System . Globalization ;
3+ using ConsoleCatchall . Console . Reconciliation . Spreadsheets ;
4+ using Interfaces ;
5+ using Interfaces . Constants ;
6+ using Interfaces . DTOs ;
7+
8+ namespace ConsoleCatchall . Console . Reconciliation . Loaders
9+ {
10+ internal class BudgetingMonthService
11+ {
12+ private readonly IInputOutput _input_output ;
13+
14+ public BudgetingMonthService ( IInputOutput input_output )
15+ {
16+ _input_output = input_output ;
17+ }
18+
19+ public BudgetingMonths Recursively_ask_for_budgeting_months ( ISpreadsheet spreadsheet )
20+ {
21+ DateTime next_unplanned_month = Get_next_unplanned_month ( spreadsheet ) ;
22+ int last_month_for_budget_planning = Get_last_month_for_budget_planning ( spreadsheet , next_unplanned_month . Month ) ;
23+ var budgeting_months = new BudgetingMonths
24+ {
25+ Next_unplanned_month = next_unplanned_month . Month ,
26+ Last_month_for_budget_planning = last_month_for_budget_planning ,
27+ Start_year = next_unplanned_month . Year
28+ } ;
29+ if ( last_month_for_budget_planning != 0 )
30+ {
31+ budgeting_months . Last_month_for_budget_planning = Confirm_budgeting_month_choices_with_user ( budgeting_months , spreadsheet ) ;
32+ }
33+ return budgeting_months ;
34+ }
35+
36+ private DateTime Get_next_unplanned_month ( ISpreadsheet spreadsheet )
37+ {
38+ DateTime default_month = DateTime . Today ;
39+ DateTime next_unplanned_month = default_month ;
40+ bool bad_input = false ;
41+ try
42+ {
43+ next_unplanned_month = spreadsheet . Get_next_unplanned_month ( ) ;
44+ }
45+ catch ( Exception )
46+ {
47+ string new_month = _input_output . Get_input ( ReconConsts . CantFindMortgageRow ) ;
48+ try
49+ {
50+ if ( ! String . IsNullOrEmpty ( new_month ) && Char . IsDigit ( new_month [ 0 ] ) )
51+ {
52+ int actual_month = Convert . ToInt32 ( new_month ) ;
53+ if ( actual_month < 1 || actual_month > 12 )
54+ {
55+ bad_input = true ;
56+ }
57+ else
58+ {
59+ var year = default_month . Year ;
60+ if ( actual_month < default_month . Month )
61+ {
62+ year ++ ;
63+ }
64+ next_unplanned_month = new DateTime ( year , actual_month , 1 ) ;
65+ }
66+ }
67+ else
68+ {
69+ bad_input = true ;
70+ }
71+ }
72+ catch ( Exception )
73+ {
74+ bad_input = true ;
75+ }
76+ }
77+
78+ if ( bad_input )
79+ {
80+ _input_output . Output_line ( ReconConsts . DefaultUnplannedMonth ) ;
81+ next_unplanned_month = default_month ;
82+ }
83+
84+ return next_unplanned_month ;
85+ }
86+
87+ private int Get_last_month_for_budget_planning ( ISpreadsheet spreadsheet , int next_unplanned_month )
88+ {
89+ string next_unplanned_month_as_string = CultureInfo . CurrentCulture . DateTimeFormat . GetMonthName ( next_unplanned_month ) ;
90+ var request_to_enter_month = String . Format ( ReconConsts . EnterMonths , next_unplanned_month_as_string ) ;
91+ string month = _input_output . Get_input ( request_to_enter_month ) ;
92+ int result = 0 ;
93+
94+ try
95+ {
96+ if ( ! String . IsNullOrEmpty ( month ) && Char . IsDigit ( month [ 0 ] ) )
97+ {
98+ result = Convert . ToInt32 ( month ) ;
99+ if ( result < 1 || result > 12 )
100+ {
101+ result = 0 ;
102+ }
103+ }
104+ }
105+ catch ( Exception )
106+ {
107+ // Ignore it and return zero by default.
108+ }
109+
110+ result = Handle_zero_month_choice_result ( result , spreadsheet , next_unplanned_month ) ;
111+ return result ;
112+ }
113+
114+ private int Confirm_budgeting_month_choices_with_user ( BudgetingMonths budgeting_months , ISpreadsheet spreadsheet )
115+ {
116+ var new_result = budgeting_months . Last_month_for_budget_planning ;
117+ string input = Get_response_to_budgeting_months_confirmation_message ( budgeting_months ) ;
118+
119+ if ( ! String . IsNullOrEmpty ( input ) && input . ToUpper ( ) == "Y" )
120+ {
121+ // I know this doesn't really do anything but I found the if statement easier to parse this way round.
122+ new_result = budgeting_months . Last_month_for_budget_planning ;
123+ }
124+ else
125+ {
126+ // Recursion ftw!
127+ new_result = Get_last_month_for_budget_planning ( spreadsheet , budgeting_months . Next_unplanned_month ) ;
128+ }
129+
130+ return new_result ;
131+ }
132+
133+ private string Get_response_to_budgeting_months_confirmation_message ( BudgetingMonths budgeting_months )
134+ {
135+ string first_month = CultureInfo . CurrentCulture . DateTimeFormat . GetAbbreviatedMonthName ( budgeting_months . Next_unplanned_month ) ;
136+ string second_month = CultureInfo . CurrentCulture . DateTimeFormat . GetAbbreviatedMonthName ( budgeting_months . Last_month_for_budget_planning ) ;
137+
138+ int month_span = budgeting_months . Num_budgeting_months ( ) ;
139+
140+ var confirmation_text = String . Format ( ReconConsts . ConfirmMonthInterval , first_month , second_month , month_span ) ;
141+
142+ return _input_output . Get_input ( confirmation_text ) ;
143+ }
144+
145+ private int Handle_zero_month_choice_result ( int chosen_month , ISpreadsheet spreadsheet , int next_unplanned_month )
146+ {
147+ var new_result = chosen_month ;
148+ if ( chosen_month == 0 )
149+ {
150+ var input = _input_output . Get_input ( ReconConsts . ConfirmBadMonth ) ;
151+
152+ if ( ! String . IsNullOrEmpty ( input ) && input . ToUpper ( ) == "Y" )
153+ {
154+ new_result = 0 ;
155+ _input_output . Output_line ( ReconConsts . ConfirmNoMonthlyBudgeting ) ;
156+ }
157+ else
158+ {
159+ // Recursion ftw!
160+ new_result = Get_last_month_for_budget_planning ( spreadsheet , next_unplanned_month ) ;
161+ }
162+ }
163+ return new_result ;
164+ }
165+ }
166+ }
0 commit comments