import 'package:flutter/material.dart'; import 'package:intaleq_maps/intaleq_maps.dart'; import '../models/military_operations_models.dart'; import '../services/hlz_assessment_engine.dart'; import '../services/military_grid_utils.dart'; /// Dedicated Helicopter Landing Zone (HLZ) Suitability HUD Sheet class TacticalHlzSheet extends StatefulWidget { final LatLng? selectedPosition; final VoidCallback onPickLocation; final VoidCallback onClose; final Function(HlzAssessmentResult) onAssessmentCompleted; const TacticalHlzSheet({ super.key, required this.selectedPosition, required this.onPickLocation, required this.onClose, required this.onAssessmentCompleted, }); @override State createState() => _TacticalHlzSheetState(); } class _TacticalHlzSheetState extends State { HelicopterType _helicopterType = HelicopterType.mediumLift; double _approachAzimuthDeg = 0.0; bool _isLoading = false; HlzAssessmentResult? _result; @override void initState() { super.initState(); _recalculate(); } @override void didUpdateWidget(covariant TacticalHlzSheet oldWidget) { super.didUpdateWidget(oldWidget); if (widget.selectedPosition != oldWidget.selectedPosition) { _recalculate(); } } Future _recalculate() async { if (widget.selectedPosition == null) { setState(() => _result = null); return; } setState(() => _isLoading = true); try { final res = await HlzAssessmentEngine.assessLandingZone( center: widget.selectedPosition!, helicopterType: _helicopterType, approachAzimuthDeg: _approachAzimuthDeg, ); if (mounted) { setState(() { _result = res; _isLoading = false; }); widget.onAssessmentCompleted(res); } } catch (e) { if (mounted) setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return Container( decoration: const BoxDecoration( color: Color(0xFF090E1A), borderRadius: BorderRadius.vertical(top: Radius.circular(20)), border: Border(top: BorderSide(color: Color(0xFF10B981), width: 1.5)), boxShadow: [ BoxShadow(color: Colors.black87, blurRadius: 24, spreadRadius: 4), ], ), child: SafeArea( top: false, child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // ── Header ─────────────────────────────────────────── Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: const Color(0xFF10B981).withAlpha(40), borderRadius: BorderRadius.circular(10), border: Border.all(color: const Color(0xFF10B981)), ), child: const Icon(Icons.flight_land, color: Color(0xFF34D399), size: 20), ), const SizedBox(width: 10), const Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'تقييم مهابط الطيران العامودي (HLZ Assessment)', style: TextStyle( color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold, ), ), Text( 'فحص ميلان الأرض والعوائق وممرات الاقتراب الآمن', style: TextStyle(color: Color(0xFF94A3B8), fontSize: 10), ), ], ), ), IconButton( icon: const Icon(Icons.close, color: Colors.white70, size: 20), onPressed: widget.onClose, ), ], ), const SizedBox(height: 14), // ── Helicopter Type Selector ────────────────────────── Row( children: [ _buildTypeTab( type: HelicopterType.lightUtility, title: 'طوافة خفيفة', subtitle: 'Bell 407 (قطر 50م)', ), const SizedBox(width: 8), _buildTypeTab( type: HelicopterType.mediumLift, title: 'طوافة متوسطة', subtitle: 'UH-60 / AH-64 (قطر 80م)', ), const SizedBox(width: 8), _buildTypeTab( type: HelicopterType.heavyTransport, title: 'نقل ثقيل', subtitle: 'CH-47 (قطر 120م)', ), ], ), const SizedBox(height: 12), // ── Location Picker Card ────────────────────────────── InkWell( onTap: widget.onPickLocation, borderRadius: BorderRadius.circular(10), child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: const Color(0xFF0F172A), borderRadius: BorderRadius.circular(10), border: Border.all( color: widget.selectedPosition != null ? const Color(0xFF10B981) : Colors.white12, ), ), child: Row( children: [ const Icon(Icons.location_on, color: Color(0xFF34D399), size: 18), const SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('موقع المهبط المقترح:', style: TextStyle(color: Color(0xFF94A3B8), fontSize: 10)), const SizedBox(height: 2), Text( widget.selectedPosition != null ? MilitaryGridUtils.latLngToMgrs( widget.selectedPosition!.latitude, widget.selectedPosition!.longitude, ) : 'انقر لتحديد موقع المهبط على الخريطة...', style: TextStyle( color: widget.selectedPosition != null ? Colors.white : Colors.white54, fontSize: 12, fontFamily: 'monospace', fontWeight: FontWeight.bold, ), ), ], ), ), const Icon(Icons.touch_app, color: Color(0xFF34D399), size: 18), ], ), ), ), const SizedBox(height: 12), // ── Approach Corridor Slider ────────────────────────── Row( children: [ const Icon(Icons.navigation, color: Color(0xFF38BDF8), size: 16), const SizedBox(width: 6), Text( 'ممر الاقتراب: ${_approachAzimuthDeg.toInt()}° (${MilitaryGridUtils.azimuthToCardinalArabic(_approachAzimuthDeg)})', style: const TextStyle(color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold), ), ], ), Slider( value: _approachAzimuthDeg, min: 0, max: 350, divisions: 35, activeColor: const Color(0xFF10B981), inactiveColor: const Color(0xFF1E293B), onChanged: (v) { setState(() => _approachAzimuthDeg = v); _recalculate(); }, ), // ── Assessment Results ──────────────────────────────── if (_isLoading) const Center( child: Padding( padding: EdgeInsets.all(16), child: CircularProgressIndicator(color: Color(0xFF10B981)), ), ) else if (_result != null) ...[ // Suitability Badge Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: _result!.gradeColor.withAlpha(25), borderRadius: BorderRadius.circular(10), border: Border.all(color: _result!.gradeColor), ), child: Row( children: [ Icon(Icons.verified, color: _result!.gradeColor, size: 20), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _result!.suitabilityGrade, style: TextStyle( color: _result!.gradeColor, fontSize: 13, fontWeight: FontWeight.w900, ), ), Text( 'منسوب الأرض: ${_result!.groundElevationM.toInt()}م • أقصى ميل: ${_result!.maxSlopePercent}%', style: const TextStyle(color: Colors.white70, fontSize: 10.5), ), ], ), ), ], ), ), const SizedBox(height: 10), // Metrics Grid Row( children: [ _buildMetricCard( title: 'أقصى انحدار للأرض', value: '${_result!.maxSlopePercent}%', status: _result!.isSlopeAcceptable ? 'ضمن الحدود' : 'شديد الانحدار', statusColor: _result!.isSlopeAcceptable ? const Color(0xFF10B981) : const Color(0xFFEF4444), ), const SizedBox(width: 8), _buildMetricCard( title: 'خلو العوائق 500م', value: _result!.isObstacleClear ? 'ممر آمن' : 'عوائق قريبة', status: _result!.isObstacleClear ? 'خالي من التلال' : 'تلال في الممر', statusColor: _result!.isObstacleClear ? const Color(0xFF10B981) : const Color(0xFFEF4444), ), ], ), ], ], ), ), ), ); } Widget _buildTypeTab({ required HelicopterType type, required String title, required String subtitle, }) { final isSelected = _helicopterType == type; return Expanded( child: InkWell( onTap: () { setState(() => _helicopterType = type); _recalculate(); }, borderRadius: BorderRadius.circular(10), child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: isSelected ? const Color(0xFF10B981).withAlpha(40) : const Color(0xFF0F172A), borderRadius: BorderRadius.circular(10), border: Border.all( color: isSelected ? const Color(0xFF10B981) : Colors.white12, ), ), child: Column( children: [ Text( title, style: TextStyle( color: isSelected ? Colors.white : const Color(0xFF94A3B8), fontSize: 10.5, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), const SizedBox(height: 2), Text( subtitle, style: TextStyle( color: isSelected ? const Color(0xFF34D399) : Colors.white38, fontSize: 8.5, ), textAlign: TextAlign.center, ), ], ), ), ), ); } Widget _buildMetricCard({ required String title, required String value, required String status, required Color statusColor, }) { return Expanded( child: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: const Color(0xFF0F172A), borderRadius: BorderRadius.circular(10), border: Border.all(color: Colors.white12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: const TextStyle(color: Color(0xFF94A3B8), fontSize: 9.5)), const SizedBox(height: 3), Text(value, style: const TextStyle(color: Colors.white, fontSize: 13, fontWeight: FontWeight.bold)), Text(status, style: TextStyle(color: statusColor, fontSize: 9.5)), ], ), ), ); } }