// lib/models/in_situ_sampling_data.dart import 'dart:io'; import 'dart:convert'; // Added for jsonEncode import 'package:environment_monitoring_app/models/marine_manual_npe_report_data.dart'; /// A data model class to hold all information for the multi-step /// In-Situ Sampling form. class InSituSamplingData { // --- Step 1: Sampling & Station Info --- String? firstSamplerName; int? firstSamplerUserId; Map? secondSampler; String? samplingDate; String? samplingTime; String? samplingType; String? sampleIdCode; String? selectedStateName; String? selectedCategoryName; Map? selectedStation; String? stationLatitude; String? stationLongitude; String? currentLatitude; String? currentLongitude; double? distanceDifferenceInKm; String? distanceDifferenceRemarks; // --- Step 2: Site Info & Photos --- String? weather; String? tideLevel; String? seaCondition; String? eventRemarks; String? labRemarks; File? leftLandViewImage; File? rightLandViewImage; File? waterFillingImage; File? seawaterColorImage; File? phPaperImage; File? optionalImage1; String? optionalRemark1; File? optionalImage2; String? optionalRemark2; File? optionalImage3; String? optionalRemark3; File? optionalImage4; String? optionalRemark4; // --- Step 3: Data Capture --- String? sondeId; String? dataCaptureDate; String? dataCaptureTime; double? oxygenConcentration; double? oxygenSaturation; double? ph; double? salinity; double? electricalConductivity; double? temperature; double? tds; double? turbidity; double? tss; double? batteryVoltage; // --- Post-Submission Status --- String? submissionStatus; String? submissionMessage; String? reportId; // --- START: NPE Report Compatibility Fields --- Map npeFieldObservations = { 'Oil slick on the water surface/ Oil spill': false, 'Discoloration of the sea water': false, 'Formation of foam on the surface': false, 'Coral bleaching or dead corals': false, 'Observation of tar balls': false, 'Excessive debris': false, 'Red tides or algae blooms': false, 'Silt plume': false, 'Foul smell': false, 'Others': false, }; String? npeOthersObservationRemark; String? npePossibleSource; File? npeImage1; File? npeImage2; File? npeImage3; File? npeImage4; // --- END: NPE Report Compatibility Fields --- InSituSamplingData({ this.samplingDate, this.samplingTime, }); /// Creates a pre-populated NPE Report object from the current In-Situ data. MarineManualNpeReportData toNpeReportData() { final npeData = MarineManualNpeReportData(); npeData.firstSamplerName = firstSamplerName; npeData.firstSamplerUserId = firstSamplerUserId; npeData.eventDate = samplingDate; npeData.eventTime = samplingTime; npeData.selectedStation = selectedStation; npeData.latitude = currentLatitude; npeData.longitude = currentLongitude; npeData.oxygenSaturation = oxygenSaturation; npeData.electricalConductivity = electricalConductivity; npeData.oxygenConcentration = oxygenConcentration; npeData.turbidity = turbidity; npeData.ph = ph; npeData.temperature = temperature; npeData.possibleSource = eventRemarks; if ((turbidity ?? 0) > 50) npeData.fieldObservations['Silt plume'] = true; if ((oxygenConcentration ?? 999) < 4) npeData.fieldObservations['Foul smell'] = true; final availableImages = [ leftLandViewImage, rightLandViewImage, waterFillingImage, seawaterColorImage, phPaperImage, optionalImage1, optionalImage2, optionalImage3, optionalImage4, ].where((img) => img != null).cast().toList(); if (availableImages.isNotEmpty) npeData.image1 = availableImages[0]; if (availableImages.length > 1) npeData.image2 = availableImages[1]; if (availableImages.length > 2) npeData.image3 = availableImages[2]; if (availableImages.length > 3) npeData.image4 = availableImages[3]; return npeData; } factory InSituSamplingData.fromJson(Map json) { double? doubleFromJson(dynamic value) { if (value is num) return value.toDouble(); if (value is String) return double.tryParse(value); return null; } int? intFromJson(dynamic value) { if (value is int) return value; if (value is String) return int.tryParse(value); return null; } File? fileFromPath(dynamic path) => (path is String && path.isNotEmpty) ? File(path) : null; final data = InSituSamplingData(); data.firstSamplerName = json['first_sampler_name']; data.firstSamplerUserId = intFromJson(json['first_sampler_user_id']); data.secondSampler = json['secondSampler'] ?? json['second_sampler']; data.samplingDate = json['sampling_date'] ?? json['man_date']; data.samplingTime = json['sampling_time'] ?? json['man_time']; data.samplingType = json['sampling_type']; data.sampleIdCode = json['sample_id_code']; data.selectedStateName = json['selected_state_name']; data.selectedCategoryName = json['selected_category_name']; data.selectedStation = json['selectedStation']; data.stationLatitude = json['station_latitude']; data.stationLongitude = json['station_longitude']; data.currentLatitude = json['current_latitude']?.toString(); data.currentLongitude = json['current_longitude']?.toString(); data.distanceDifferenceInKm = doubleFromJson(json['distance_difference_in_km']); data.distanceDifferenceRemarks = json['distance_difference_remarks']; data.weather = json['weather']; data.tideLevel = json['tide_level']; data.seaCondition = json['sea_condition']; data.eventRemarks = json['event_remarks']; data.labRemarks = json['lab_remarks']; data.optionalRemark1 = json['man_optional_photo_01_remarks']; data.optionalRemark2 = json['man_optional_photo_02_remarks']; data.optionalRemark3 = json['man_optional_photo_03_remarks']; data.optionalRemark4 = json['man_optional_photo_04_remarks']; data.sondeId = json['sonde_id']; data.dataCaptureDate = json['data_capture_date']; data.dataCaptureTime = json['data_capture_time']; data.oxygenConcentration = doubleFromJson(json['oxygen_concentration']); data.oxygenSaturation = doubleFromJson(json['oxygen_saturation']); data.ph = doubleFromJson(json['ph']); data.salinity = doubleFromJson(json['salinity']); data.electricalConductivity = doubleFromJson(json['electrical_conductivity']); data.temperature = doubleFromJson(json['temperature']); data.tds = doubleFromJson(json['tds']); data.turbidity = doubleFromJson(json['turbidity']); data.tss = doubleFromJson(json['tss']); data.batteryVoltage = doubleFromJson(json['battery_voltage']); data.submissionStatus = json['submission_status']; data.submissionMessage = json['submission_message']; data.reportId = json['report_id']?.toString(); data.leftLandViewImage = fileFromPath(json['man_left_side_land_view']); data.rightLandViewImage = fileFromPath(json['man_right_side_land_view']); data.waterFillingImage = fileFromPath(json['man_filling_water_into_sample_bottle']); data.seawaterColorImage = fileFromPath(json['man_seawater_in_clear_glass_bottle']); data.phPaperImage = fileFromPath(json['man_examine_preservative_ph_paper']); data.optionalImage1 = fileFromPath(json['man_optional_photo_01']); data.optionalImage2 = fileFromPath(json['man_optional_photo_02']); data.optionalImage3 = fileFromPath(json['man_optional_photo_03']); data.optionalImage4 = fileFromPath(json['man_optional_photo_04']); if (json['npe_field_observations'] is Map) { data.npeFieldObservations = Map.from(json['npe_field_observations']); } data.npeOthersObservationRemark = json['npe_others_observation_remark']; data.npePossibleSource = json['npe_possible_source']; data.npeImage1 = fileFromPath(json['npe_image_1']); data.npeImage2 = fileFromPath(json['npe_image_2']); data.npeImage3 = fileFromPath(json['npe_image_3']); data.npeImage4 = fileFromPath(json['npe_image_4']); return data; } Map toMap() { return { 'first_sampler_name': firstSamplerName, 'first_sampler_user_id': firstSamplerUserId, 'secondSampler': secondSampler, 'sampling_date': samplingDate, 'sampling_time': samplingTime, 'sampling_type': samplingType, 'sample_id_code': sampleIdCode, 'selected_state_name': selectedStateName, 'selected_category_name': selectedCategoryName, 'selectedStation': selectedStation, 'station_latitude': stationLatitude, 'station_longitude': stationLongitude, 'current_latitude': currentLatitude, 'current_longitude': currentLongitude, 'distance_difference_in_km': distanceDifferenceInKm, 'distance_difference_remarks': distanceDifferenceRemarks, 'weather': weather, 'tide_level': tideLevel, 'sea_condition': seaCondition, 'event_remarks': eventRemarks, 'lab_remarks': labRemarks, 'man_optional_photo_01_remarks': optionalRemark1, 'man_optional_photo_02_remarks': optionalRemark2, 'man_optional_photo_03_remarks': optionalRemark3, 'man_optional_photo_04_remarks': optionalRemark4, 'sonde_id': sondeId, 'data_capture_date': dataCaptureDate, 'data_capture_time': dataCaptureTime, 'oxygen_concentration': oxygenConcentration, 'oxygen_saturation': oxygenSaturation, 'ph': ph, 'salinity': salinity, 'electrical_conductivity': electricalConductivity, 'temperature': temperature, 'tds': tds, 'turbidity': turbidity, 'tss': tss, 'battery_voltage': batteryVoltage, 'submission_status': submissionStatus, 'submission_message': submissionMessage, 'report_id': reportId, 'npe_field_observations': npeFieldObservations, 'npe_others_observation_remark': npeOthersObservationRemark, 'npe_possible_source': npePossibleSource, }; } /// Creates a single JSON object for 'db.json'. FORCING ALL VALUES TO STRING. String toDbJson() { final data = { 'battery_cap': (batteryVoltage ?? "NULL").toString(), 'device_name': (sondeId ?? "").toString(), 'sampling_type': (samplingType ?? "").toString(), 'report_id': (reportId ?? "").toString(), 'sampler_2ndname': (secondSampler?['first_name'] ?? "").toString(), 'sample_state': (selectedStateName ?? "").toString(), 'station_id': (selectedStation?['man_station_code'] ?? "").toString(), 'tech_id': (firstSamplerUserId ?? "NULL").toString(), 'tech_phonenum': "", 'tech_name': (firstSamplerName ?? "").toString(), 'latitude': (stationLatitude ?? "").toString(), 'longitude': (stationLongitude ?? "").toString(), 'record_dt': (samplingDate != null && samplingTime != null) ? '$samplingDate $samplingTime' : "", 'do_mgl': (oxygenConcentration ?? "NULL").toString(), 'do_sat': (oxygenSaturation ?? "NULL").toString(), 'ph': (ph ?? "NULL").toString(), 'salinity': (salinity ?? "NULL").toString(), 'tss': (tss ?? "NULL").toString(), 'temperature': (temperature ?? "NULL").toString(), 'turbidity': (turbidity ?? "NULL").toString(), 'tds': (tds ?? "NULL").toString(), 'electric_conductivity': (electricalConductivity ?? "NULL").toString(), 'sample_id': (sampleIdCode ?? "").toString(), 'tarball': "No", 'weather': (weather ?? "").toString(), 'tide_lvl': (tideLevel ?? "").toString(), 'sea_cond': (seaCondition ?? "").toString(), 'remarks_event': (eventRemarks ?? "").toString(), 'remarks_lab': (labRemarks ?? "").toString(), }; return jsonEncode(data); } /// Creates a JSON object for basic form info. FORCING ALL VALUES TO STRING. String toBasicFormJson() { final data = { 'tech_name': (firstSamplerName ?? "").toString(), 'sampler_2ndname': (secondSampler?['first_name'] ?? "").toString(), 'sample_date': (samplingDate ?? "").toString(), 'sample_time': (samplingTime ?? "").toString(), 'sampling_type': (samplingType ?? "").toString(), 'sample_state': (selectedStateName ?? "").toString(), 'sample_category': (selectedCategoryName ?? "").toString(), 'station_id': (selectedStation?['man_station_code'] ?? "").toString(), 'station_latitude': (stationLatitude ?? "").toString(), 'station_longitude': (stationLongitude ?? "").toString(), 'latitude': (currentLatitude ?? "").toString(), 'longitude': (currentLongitude ?? "").toString(), 'sample_id': (sampleIdCode ?? "").toString(), }; return jsonEncode(data); } /// Creates a JSON object for sensor readings. FORCING ALL VALUES TO STRING. String toReadingJson() { final data = { 'do_mgl': (oxygenConcentration ?? "NULL").toString(), 'do_sat': (oxygenSaturation ?? "NULL").toString(), 'ph': (ph ?? "NULL").toString(), 'salinity': (salinity ?? "NULL").toString(), 'tds': (tds ?? "NULL").toString(), 'tss': (tss ?? "NULL").toString(), 'temperature': (temperature ?? "NULL").toString(), 'turbidity': (turbidity ?? "NULL").toString(), 'electric_conductivity': (electricalConductivity ?? "NULL").toString(), 'date_sampling_reading': (dataCaptureDate ?? "").toString(), 'time_sampling_reading': (dataCaptureTime ?? "").toString(), }; return jsonEncode(data); } /// Creates a JSON object for manual info. FORCING ALL VALUES TO STRING. String toManualInfoJson() { final data = { 'tarball': "", 'weather': (weather ?? "").toString(), 'tide_lvl': (tideLevel ?? "").toString(), 'sea_cond': (seaCondition ?? "").toString(), 'remarks_event': (eventRemarks ?? "").toString(), 'remarks_lab': (labRemarks ?? "").toString(), }; return jsonEncode(data); } Map toApiFormData() { final Map map = {}; void add(String key, dynamic value) { if (value != null) { String stringValue = (value is double) ? ((value == -999.0) ? 'NULL' : value.toStringAsFixed(5)) : value.toString(); if (stringValue.isNotEmpty) map[key] = stringValue; } } add('station_id', selectedStation?['station_id']); add('man_date', samplingDate); add('man_time', samplingTime); add('first_sampler_user_id', firstSamplerUserId); add('man_second_sampler_id', secondSampler?['user_id']); add('man_type', samplingType); add('man_sample_id_code', sampleIdCode); add('man_current_latitude', currentLatitude); add('man_current_longitude', currentLongitude); add('man_distance_difference', distanceDifferenceInKm); add('man_distance_difference_remarks', distanceDifferenceRemarks); add('man_weather', weather); add('man_tide_level', tideLevel); add('man_sea_condition', seaCondition); add('man_event_remark', eventRemarks); add('man_lab_remark', labRemarks); add('man_optional_photo_01_remarks', optionalRemark1); add('man_optional_photo_02_remarks', optionalRemark2); add('man_optional_photo_03_remarks', optionalRemark3); add('man_optional_photo_04_remarks', optionalRemark4); add('man_sondeID', sondeId); add('data_capture_date', dataCaptureDate); add('data_capture_time', dataCaptureTime); add('man_oxygen_conc', oxygenConcentration); add('man_oxygen_sat', oxygenSaturation); add('man_ph', ph); add('man_salinity', salinity); add('man_conductivity', electricalConductivity); add('man_temperature', temperature); add('man_tds', tds); add('man_turbidity', turbidity); add('man_tss', tss); add('man_battery_volt', batteryVoltage); add('first_sampler_name', firstSamplerName); add('man_station_code', selectedStation?['man_station_code']); add('man_station_name', selectedStation?['man_station_name']); return map; } Map toApiImageFiles() { return { 'man_left_side_land_view': leftLandViewImage, 'man_right_side_land_view': rightLandViewImage, 'man_filling_water_into_sample_bottle': waterFillingImage, 'man_seawater_in_clear_glass_bottle': seawaterColorImage, 'man_examine_preservative_ph_paper': phPaperImage, 'man_optional_photo_01': optionalImage1, 'man_optional_photo_02': optionalImage2, 'man_optional_photo_03': optionalImage3, 'man_optional_photo_04': optionalImage4, }; } }