Files
syncrow-app/lib/features/scene/bloc/create_scene/create_scene_bloc.dart
2024-07-28 12:04:22 +03:00

502 lines
17 KiB
Dart

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.dart';
import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
import 'package:syncrow_app/services/api/scene_api.dart';
part 'create_scene_event.dart';
part 'create_scene_state.dart';
class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
with SceneOperationsDataHelper {
CreateSceneBloc() : super(CreateSceneInitial()) {
on<CreateSceneWithTasksEvent>(_createSceneWithTasks);
on<AddTaskEvent>(_onAddSceneTask);
on<SelectedValueEvent>(_selectedValue);
on<RemoveTaskByIdEvent>(_removeTaskById);
on<ClearTaskListEvent>(_clearTaskList);
on<ClearTempTaskListEvent>(_clearTempTaskList);
on<FetchSceneTasksEvent>(_fetchSceneTasks);
on<TempHoldSceneTasksEvent>(_onTempHoldSceneTask);
on<RemoveTempTaskByIdEvent>(_removeTempTaskById);
on<RemoveFromSelectedValueById>(_removeFromSelectedValueById);
on<DeleteSceneEvent>(_deleteScene);
on<UpdateTaskEvent>(_updateTaskValue);
on<SelectConditionEvent>(_selectConditionRule);
on<SceneTypeEvent>(_sceneTypeEvent);
on<EffectiveTimePeriodEvent>(_onEffectiveTimeEvent);
}
CreateSceneEnum sceneType = CreateSceneEnum.none;
/// tab to run values and list
List<SceneStaticFunction> tasksList = [];
List<SceneStaticFunction> tempTasksList = [];
final Map<String, dynamic> selectedValues = {};
/// automation values and list
List<SceneStaticFunction> automationTasksList = [];
List<SceneStaticFunction> automationTempTasksList = [];
final Map<String, dynamic> automationSelectedValues = {};
final Map<String, String> automationComparatorValues = {};
String conditionRule = 'or';
EffectiveTime? effectiveTime;
FutureOr<void> _onAddSceneTask(AddTaskEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
if (event.isAutomation == true) {
final copyList = List<SceneStaticFunction>.from(automationTempTasksList);
automationTasksList.addAll(copyList);
automationTempTasksList.clear();
automationSelectedValues.clear();
automationComparatorValues.clear();
emit(AddSceneTask(
automationTasksList: automationTasksList,
tasksList: tasksList,
condition: conditionRule,
));
} else {
final copyList = List<SceneStaticFunction>.from(tempTasksList);
tasksList.addAll(copyList);
tempTasksList.clear();
selectedValues.clear();
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
}
}
FutureOr<void> _onTempHoldSceneTask(
TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
if (event.isAutomation == true) {
addToTempAutomationTaskList(event, emit);
} else {
addToTempTaskList(event, emit);
}
}
void addToTempTaskList(TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
bool updated = false;
for (var element in tempTasksList) {
if (element.code == event.deviceControlModel.code) {
// Update the existing function with new values
var updatedElement = element.copyWith(
operationName: event.operation,
deviceName: event.deviceName,
icon: event.icon,
code: event.deviceControlModel.code ?? '',
deviceId: event.deviceId,
functionValue: event.deviceControlModel.value,
operationDialogType: event.operationType,
operationalValues: [
SceneOperationalValue(
value: event.deviceControlModel.value,
icon: '',
),
],
);
tempTasksList[tempTasksList.indexOf(element)] = updatedElement;
selectedValues[updatedElement.code] = event.deviceControlModel.value;
updated = true;
break;
}
}
if (!updated) {
var newElement = SceneStaticFunction(
operationName: event.operation,
deviceName: event.deviceName,
icon: event.icon,
code: event.deviceControlModel.code ?? '',
operationDialogType: event.operationType,
deviceId: event.deviceId,
functionValue: event.deviceControlModel.value,
operationalValues: [
SceneOperationalValue(
value: event.deviceControlModel.value,
icon: '',
),
],
);
tempTasksList.add(newElement);
selectedValues[newElement.code] = event.deviceControlModel.value;
}
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
}
void addToTempAutomationTaskList(TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
bool updated = false;
for (var element in automationTempTasksList) {
if (element.code == event.deviceControlModel.code) {
// Update the existing function with new values
var updatedElement = element.copyWith(
operationName: event.operation,
deviceName: event.deviceName,
icon: event.icon,
code: event.deviceControlModel.code ?? '',
deviceId: event.deviceId,
functionValue: event.deviceControlModel.value,
operationDialogType: event.operationType,
operationalValues: [
SceneOperationalValue(
value: event.deviceControlModel.value,
icon: '',
),
],
comparator: automationComparatorValues[element.code],
);
automationTempTasksList[automationTempTasksList.indexOf(element)] = updatedElement;
automationSelectedValues[updatedElement.code] = event.deviceControlModel.value;
updated = true;
break;
}
}
if (!updated) {
var newElement = SceneStaticFunction(
operationName: event.operation,
deviceName: event.deviceName,
icon: event.icon,
code: event.deviceControlModel.code ?? '',
operationDialogType: event.operationType,
deviceId: event.deviceId,
functionValue: event.deviceControlModel.value,
operationalValues: [
SceneOperationalValue(
value: event.deviceControlModel.value,
icon: '',
),
],
comparator: automationComparatorValues[event.deviceControlModel.code] ?? '==',
);
automationTempTasksList.add(newElement);
automationSelectedValues[newElement.code] = event.deviceControlModel.value;
}
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
}
FutureOr<void> _selectedValue(SelectedValueEvent event, Emitter<CreateSceneState> emit) {
if (event.isAutomation == true) {
automationSelectedValues[event.code] = event.value;
automationComparatorValues[event.code] = event.comparator ?? '==';
// Update the comparator value for the specific task in automationTasksList
for (int i = 0; i < automationTasksList.length; i++) {
if (automationTasksList[i].code == event.code) {
automationTasksList[i] = automationTasksList[i].copyWith(
comparator: event.comparator ?? '==',
functionValue: event.value,
);
break;
}
}
} else {
selectedValues[event.code] = event.value;
}
emit(SelectedTaskValueState(value: event.value));
emit(AddSceneTask(
tasksList: List.from(tasksList),
automationTasksList: List.from(
automationTasksList,
),
condition: conditionRule,
));
}
FutureOr<void> _removeTaskById(RemoveTaskByIdEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
if (event.isAutomation == true) {
for (var element in automationTasksList) {
if (element.uniqueCustomId == event.taskId) {
automationTasksList.remove(element);
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
break;
}
}
} else {
for (var element in tasksList) {
if (element.uniqueCustomId == event.taskId) {
tasksList.remove(element);
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
break;
}
}
}
}
FutureOr<void> _removeTempTaskById(
RemoveTempTaskByIdEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
if (event.isAutomation == true) {
for (var element in automationTempTasksList) {
if (element.uniqueCustomId == event.code) {
automationTempTasksList.remove(element);
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
break;
}
}
} else {
for (var element in tempTasksList) {
if (element.code == event.code) {
tempTasksList.remove(element);
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
break;
}
}
}
}
FutureOr<void> _createSceneWithTasks(
CreateSceneWithTasksEvent event, Emitter<CreateSceneState> emit) async {
emit(CreateSceneLoading());
try {
dynamic response;
if (event.createSceneModel != null) {
response = event.updateScene
? await SceneApi.updateScene(event.createSceneModel!, event.sceneId)
: await SceneApi.createScene(event.createSceneModel!);
} else if (event.createAutomationModel != null) {
response = event.updateScene
? await SceneApi.updateAutomation(event.createAutomationModel!, event.sceneId)
: await SceneApi.createAutomation(event.createAutomationModel!);
}
if (response['success'] == true) {
tasksList.clear();
tempTasksList.clear();
selectedValues.clear();
automationTasksList.clear();
automationTempTasksList.clear();
automationSelectedValues.clear();
automationComparatorValues.clear();
effectiveTime = null;
sceneType = CreateSceneEnum.none;
conditionRule = 'or';
emit(const CreateSceneWithTasks(success: true));
} else {
emit(const CreateSceneError(message: 'Something went wrong'));
}
} catch (e) {
emit(const CreateSceneError(message: 'Something went wrong'));
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
}
}
FutureOr<void> _clearTaskList(ClearTaskListEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
automationTasksList.clear();
tasksList.clear();
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
}
FutureOr<void> _fetchSceneTasks(
FetchSceneTasksEvent event, Emitter<CreateSceneState> emit) async {
emit(CreateSceneLoading());
try {
final response = event.isAutomation
? await SceneApi.getAutomationDetails(event.sceneId)
: await SceneApi.getSceneDetails(event.sceneId);
if (response.id.isNotEmpty) {
if (event.isAutomation) {
automationTasksList = List<SceneStaticFunction>.from(getTaskListFunctionsFromApi(
actions: [], isAutomation: true, conditions: response.conditions));
tasksList = List<SceneStaticFunction>.from(
getTaskListFunctionsFromApi(actions: response.actions, isAutomation: false));
conditionRule = response.decisionExpr ?? conditionRule;
emit(AddSceneTask(
automationTasksList: automationTasksList,
tasksList: tasksList,
condition: conditionRule,
));
} else {
tasksList = List<SceneStaticFunction>.from(
getTaskListFunctionsFromApi(actions: response.actions, isAutomation: false));
emit(AddSceneTask(
tasksList: tasksList,
condition: conditionRule,
));
}
} else {
emit(const CreateSceneError(message: 'Something went wrong'));
}
} catch (e) {
emit(const CreateSceneError(message: 'Something went wrong'));
}
}
FutureOr<void> _clearTempTaskList(ClearTempTaskListEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
if (event.isAutomation == true) {
automationTempTasksList.clear();
automationSelectedValues.clear();
automationComparatorValues.clear();
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
} else {
tempTasksList.clear();
selectedValues.clear();
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
}
}
FutureOr<void> _removeFromSelectedValueById(
RemoveFromSelectedValueById event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
if (event.isAutomation == true) {
if (automationSelectedValues.containsKey(event.code)) {
automationSelectedValues.remove(event.code);
automationComparatorValues.remove(event.code);
emit(const SelectedTaskValueState(value: null));
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
}
} else {
if (selectedValues.containsKey(event.code)) {
selectedValues.remove(event.code);
emit(const SelectedTaskValueState(value: null));
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
}
}
}
FutureOr<void> _deleteScene(DeleteSceneEvent event, Emitter<CreateSceneState> emit) async {
emit(DeleteSceneLoading());
try {
final response = sceneType.name == CreateSceneEnum.deviceStatusChanges.name
? await SceneApi.deleteAutomation(automationId: event.sceneId, unitUuid: event.unitUuid)
: await SceneApi.deleteScene(sceneId: event.sceneId, unitUuid: event.unitUuid);
if (response == true) {
emit(const DeleteSceneSuccess(true));
} else {
emit(const DeleteSceneError(message: 'Something went wrong'));
}
} catch (e) {
emit(const DeleteSceneError(message: 'Something went wrong'));
}
}
FutureOr<void> _updateTaskValue(UpdateTaskEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
if (event.isAutomation == true) {
for (var i = 0; i < automationTasksList.length; i++) {
if (automationTasksList[i].uniqueCustomId == event.taskId) {
automationTasksList[i] = automationTasksList[i].copyWith(
functionValue: event.newValue,
);
break;
}
}
} else {
for (var i = 0; i < tasksList.length; i++) {
if (tasksList[i].uniqueCustomId == event.taskId) {
tasksList[i] = tasksList[i].copyWith(
functionValue: event.newValue,
);
break;
}
}
}
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
}
FutureOr<void> _selectConditionRule(SelectConditionEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneInitial());
if (event.condition.contains('any')) {
conditionRule = 'or';
} else {
conditionRule = 'and';
}
emit(AddSceneTask(
tasksList: tasksList,
automationTasksList: automationTasksList,
condition: conditionRule,
));
}
FutureOr<void> _sceneTypeEvent(SceneTypeEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneInitial());
if (event.type == CreateSceneEnum.tabToRun) {
sceneType = CreateSceneEnum.tabToRun;
} else if (event.type == CreateSceneEnum.deviceStatusChanges) {
sceneType = CreateSceneEnum.deviceStatusChanges;
} else {
sceneType = CreateSceneEnum.none;
}
emit(SceneTypeState(event.type));
}
FutureOr<void> _onEffectiveTimeEvent(
EffectiveTimePeriodEvent event, Emitter<CreateSceneState> emit) {
effectiveTime = event.period;
}
}