import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_web/pages/routiens/models/ac/ac_function.dart'; import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/routiens/bloc/functions_bloc/functions_bloc_bloc.dart'; class ACHelper { static Future?> showACFunctionsDialog( BuildContext context, List> functions, ) async { List acFunctions = functions.whereType().toList(); // Initialize the FunctionBloc with existing functions final initialFunctions = acFunctions .map((f) => DeviceFunctionData( entityId: '', function: f.code, operationName: f.operationName, value: null, )) .toList(); return showDialog?>( context: context, builder: (BuildContext context) { return BlocProvider( create: (_) => FunctionBloc()..add(InitializeFunctions(initialFunctions)), child: AlertDialog( contentPadding: EdgeInsets.zero, content: BlocBuilder( builder: (context, state) { debugPrint( 'Current state - Selected: ${state.selectedFunction}, Functions: ${state.functions}'); final selectedFunction = state.selectedFunction; final selectedFunctionData = selectedFunction != null ? state.functions.firstWhere( (f) => f.function == selectedFunction, orElse: () => DeviceFunctionData( entityId: '', function: selectedFunction, operationName: '', value: null, ), ) : null; return Container( width: selectedFunction != null ? 600 : 360, height: 450, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), ), padding: const EdgeInsets.only(top: 20), child: Column( mainAxisSize: MainAxisSize.min, children: [ const DialogHeader('AC Functions'), Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Function list SizedBox( width: selectedFunction != null ? 320 : 360, child: _buildFunctionsList( context, acFunctions, (functionCode) => context.read().add( AddFunction( functionData: DeviceFunctionData( entityId: '', function: functionCode, operationName: '', value: null, )), ), ), ), // Value selector if (selectedFunction != null) Expanded( child: _buildValueSelector( context, selectedFunction, selectedFunctionData, (value) => context.read().add( UpdateFunctionValue( function: selectedFunction, value: value, ), ), (condition) => context.read().add( UpdateFunctionCondition( function: selectedFunction, condition: condition, ), ), acFunctions, ), ), ], ), ), DialogFooter( onCancel: () { Navigator.pop(context); }, onConfirm: selectedFunction != null && selectedFunctionData?.value != null ? () {} : null, isConfirmEnabled: selectedFunction != null, ), ], ), ); }, ), ), ); }, ).then((value) { return value; }); } /// Build functions list for AC functions dialog static Widget _buildFunctionsList( BuildContext context, List acFunctions, Function(String) onFunctionSelected, ) { return ListView.separated( shrinkWrap: false, physics: const AlwaysScrollableScrollPhysics(), itemCount: acFunctions.length, separatorBuilder: (context, index) => const Padding( padding: EdgeInsets.symmetric(horizontal: 40.0), child: Divider( color: ColorsManager.dividerColor, ), ), itemBuilder: (context, index) { final function = acFunctions[index]; return ListTile( leading: SvgPicture.asset( function.icon, width: 24, height: 24, placeholderBuilder: (BuildContext context) => Container( width: 24, height: 24, color: Colors.transparent, ), ), title: Text( function.operationName, style: context.textTheme.bodyMedium, ), trailing: const Icon( Icons.arrow_forward_ios, size: 16, color: ColorsManager.textGray, ), onTap: () => onFunctionSelected(function.code), ); }, ); } /// Build value selector for AC functions dialog static Widget _buildValueSelector( BuildContext context, String selectedFunction, DeviceFunctionData? selectedFunctionData, Function(dynamic) onValueChanged, Function(String) onConditionChanged, List acFunctions, ) { if (selectedFunction == 'temp_set' || selectedFunction == 'temp_current') { final initialValue = selectedFunctionData?.value ?? 200; return _buildTemperatureSelector( context, initialValue, selectedFunctionData?.condition, onValueChanged, onConditionChanged, ); } final selectedFn = acFunctions.firstWhere((f) => f.code == selectedFunction); final values = selectedFn.getOperationalValues(); return _buildOperationalValuesList( context, values, selectedFunctionData?.value, onValueChanged, ); } /// Build temperature selector for AC functions dialog static Widget _buildTemperatureSelector( BuildContext context, dynamic initialValue, String? currentCondition, Function(dynamic) onValueChanged, Function(String) onConditionChanged, ) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ _buildConditionToggle( context, currentCondition, onConditionChanged, ), const SizedBox(height: 20), _buildTemperatureDisplay(context, initialValue), const SizedBox(height: 20), _buildTemperatureSlider( context, initialValue, onValueChanged, ), ], ); } /// Build condition toggle for AC functions dialog static Widget _buildConditionToggle( BuildContext context, String? currentCondition, Function(String) onConditionChanged, ) { final conditions = ["<", "==", ">"]; return ToggleButtons( onPressed: (int index) { onConditionChanged(conditions[index]); }, borderRadius: const BorderRadius.all(Radius.circular(8)), selectedBorderColor: ColorsManager.primaryColorWithOpacity, selectedColor: Colors.white, fillColor: ColorsManager.primaryColorWithOpacity, color: ColorsManager.primaryColorWithOpacity, constraints: const BoxConstraints( minHeight: 40.0, minWidth: 40.0, ), isSelected: conditions.map((c) => c == (currentCondition ?? "==")).toList(), children: conditions.map((c) => Text(c)).toList(), ); } /// Build temperature display for AC functions dialog static Widget _buildTemperatureDisplay( BuildContext context, dynamic initialValue) { return Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), decoration: BoxDecoration( color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: Text( '${(initialValue ?? 200) / 10}°C', style: context.textTheme.headlineMedium!.copyWith( color: ColorsManager.primaryColorWithOpacity, ), ), ); } static Widget _buildTemperatureSlider( BuildContext context, dynamic initialValue, Function(dynamic) onValueChanged, ) { return Slider( value: initialValue is int ? initialValue.toDouble() : 200.0, min: 160, max: 300, divisions: 14, label: '${((initialValue ?? 200) / 10).toInt()}°C', onChanged: (value) { onValueChanged(value.toInt()); }, ); } static Widget _buildOperationalValuesList( BuildContext context, List values, dynamic selectedValue, Function(dynamic) onValueChanged, ) { return ListView.builder( shrinkWrap: false, physics: const AlwaysScrollableScrollPhysics(), itemCount: values.length, itemBuilder: (context, index) { final value = values[index]; final isSelected = selectedValue == value.value; return ListTile( leading: SvgPicture.asset( value.icon, width: 24, height: 24, placeholderBuilder: (BuildContext context) => Container( width: 24, height: 24, color: Colors.transparent, ), ), title: Text( value.description, style: context.textTheme.bodyMedium, ), trailing: Icon( isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, size: 24, color: isSelected ? ColorsManager.primaryColorWithOpacity : ColorsManager.textGray, ), onTap: () { if (!isSelected) { onValueChanged(value.value); } }, ); }, ); } }