import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/models/ac/ac_function.dart'; import 'package:syncrow_web/pages/routines/models/ac/ac_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; class ACHelper { static Future?> showACFunctionsDialog({ required BuildContext context, required List functions, required AllDevicesModel? device, required List? deviceSelectedFunctions, required String uniqueCustomId, required bool? removeComparetors, required String dialogType, }) async { List acFunctions = functions.whereType().where((function) { if (dialogType == 'THEN') { return function.type == 'THEN' || function.type == 'BOTH'; } return function.type == 'IF' || function.type == 'BOTH'; }).toList(); // List acFunctions = functions.whereType().toList(); return showDialog?>( context: context, builder: (BuildContext context) { return BlocProvider( create: (_) => FunctionBloc() ..add(InitializeFunctions(deviceSelectedFunctions ?? [])), child: AlertDialog( contentPadding: EdgeInsets.zero, content: BlocBuilder( builder: (context, state) { final selectedFunction = state.selectedFunction; final selectedOperationName = state.selectedOperationName; final selectedFunctionData = state.addedFunctions .firstWhere((f) => f.functionCode == selectedFunction, orElse: () => DeviceFunctionData( entityId: '', functionCode: selectedFunction ?? '', operationName: '', value: 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: context, acFunctions: acFunctions, onFunctionSelected: (functionCode, operationName) => context.read().add(SelectFunction( functionCode: functionCode, operationName: operationName, )), ), ), // Value selector if (selectedFunction != null) Expanded( child: _buildValueSelector( context: context, selectedFunction: selectedFunction, selectedFunctionData: selectedFunctionData, acFunctions: acFunctions, device: device, operationName: selectedOperationName ?? '', removeComparators: removeComparetors, ), ), ], ), ), DialogFooter( onCancel: () { Navigator.pop(context); }, onConfirm: state.addedFunctions.isNotEmpty ? () { /// add the functions to the routine bloc context.read().add( AddFunctionToRoutine( state.addedFunctions, uniqueCustomId, ), ); // Return the device data to be added to the container Navigator.pop(context, { 'deviceId': functions.first.deviceId, }); } : null, isConfirmEnabled: selectedFunction != null, ), ], ), ); }, ), ), ); }, ).then((value) { return value; }); } /// Build functions list for AC functions dialog static Widget _buildFunctionsList({ required BuildContext context, required List acFunctions, required Function(String, 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, function.operationName, ), ); }, ); } /// Build value selector for AC functions dialog static Widget _buildValueSelector({ required BuildContext context, required String selectedFunction, required DeviceFunctionData? selectedFunctionData, required List acFunctions, AllDevicesModel? device, required String operationName, bool? removeComparators, }) { final initialVal = selectedFunction == 'temp_set' ? 200 : -100; if (selectedFunction == 'temp_set' || selectedFunction == 'temp_current') { final initialValue = selectedFunctionData?.value ?? initialVal; return _buildTemperatureSelector( context: context, initialValue: initialValue, selectCode: selectedFunction, currentCondition: selectedFunctionData?.condition, device: device, operationName: operationName, selectedFunctionData: selectedFunctionData, removeComparators: removeComparators, ); } final selectedFn = acFunctions.firstWhere((f) => f.code == selectedFunction); final values = selectedFn.getOperationalValues(); return _buildOperationalValuesList( context: context, values: values, selectedValue: selectedFunctionData?.value, device: device, operationName: operationName, selectCode: selectedFunction, selectedFunctionData: selectedFunctionData, ); } /// Build temperature selector for AC functions dialog static Widget _buildTemperatureSelector({ required BuildContext context, required dynamic initialValue, required String? currentCondition, required String selectCode, AllDevicesModel? device, required String operationName, DeviceFunctionData? selectedFunctionData, bool? removeComparators, }) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ if (removeComparators != true) _buildConditionToggle( context, currentCondition, selectCode, device, operationName, selectedFunctionData, ), const SizedBox(height: 20), _buildTemperatureDisplay( context, initialValue, device, operationName, selectedFunctionData, selectCode, ), const SizedBox(height: 20), _buildTemperatureSlider( context, initialValue, device, operationName, selectedFunctionData, selectCode, ), ], ); } /// Build condition toggle for AC functions dialog static Widget _buildConditionToggle( BuildContext context, String? currentCondition, String selectCode, AllDevicesModel? device, String operationName, DeviceFunctionData? selectedFunctionData, // Function(String) onConditionChanged, ) { final conditions = ["<", "==", ">"]; return ToggleButtons( onPressed: (int index) { context.read().add( AddFunction( functionData: DeviceFunctionData( entityId: device?.uuid ?? '', functionCode: selectCode, operationName: operationName, condition: conditions[index], value: selectedFunctionData?.value ?? selectCode == 'temp_set' ? 200 : -100, valueDescription: selectedFunctionData?.valueDescription, ), ), ); }, 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, AllDevicesModel? device, String operationName, DeviceFunctionData? selectedFunctionData, String selectCode, ) { final initialVal = selectCode == 'temp_set' ? 200 : -100; 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 ?? initialVal) / 10}°C', style: context.textTheme.headlineMedium!.copyWith( color: ColorsManager.primaryColorWithOpacity, ), ), ); } static Widget _buildTemperatureSlider( BuildContext context, dynamic initialValue, AllDevicesModel? device, String operationName, DeviceFunctionData? selectedFunctionData, String selectCode, ) { return Slider( value: initialValue is int ? initialValue.toDouble() : 200.0, min: selectCode == 'temp_current' ? -100 : 200, max: selectCode == 'temp_current' ? 900 : 300, divisions: 10, label: '${((initialValue ?? 160) / 10).toInt()}°C', onChanged: (value) { context.read().add( AddFunction( functionData: DeviceFunctionData( entityId: device?.uuid ?? '', functionCode: selectCode, operationName: operationName, value: value, condition: selectedFunctionData?.condition, valueDescription: selectedFunctionData?.valueDescription, ), ), ); }, ); } static Widget _buildOperationalValuesList({ required BuildContext context, required List values, required dynamic selectedValue, AllDevicesModel? device, required String operationName, required String selectCode, DeviceFunctionData? selectedFunctionData, // required 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) { context.read().add( AddFunction( functionData: DeviceFunctionData( entityId: device?.uuid ?? '', functionCode: selectCode, operationName: operationName, value: value.value, condition: selectedFunctionData?.condition, valueDescription: selectedFunctionData?.valueDescription, ), ), ); } }, ); }, ); } }