// Copyright (c) 2023 schick Informatik // Description: Windows dialog to create / edit ship calls // using BreCalClient.misc.Api; using BreCalClient.misc.Model; using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using static BreCalClient.Extensions; namespace BreCalClient { /// /// Interaction logic for EditShipcallControl.xaml /// public partial class EditShipcallControl : Window { public EditShipcallControl() { InitializeComponent(); } #region Properties public ShipcallControlModel ShipcallModel { get; set; } = new (); public Ship? SelectedShip { get { return this.comboBoxShip.SelectedItem as Ship; } } public bool ShipEditingEnabled { get { return this.buttonEditShips.Visibility == Visibility.Visible; } set { this.buttonEditShips.Visibility = value ? Visibility.Visible : Visibility.Hidden; } } public ShipApi? ShipApi { get; set; } #endregion #region Event handler private void Window_Loaded(object sender, RoutedEventArgs e) { this.comboBoxAgency.ItemsSource = BreCalLists.Participants_Agent; this.comboBoxShip.ItemsSource = BreCalLists.Ships; Array types = Enum.GetValues(typeof(ShipcallType)); List shipcallTypes = new(); bool first = true; foreach(ShipcallType shipcallType in types) { if (!first) shipcallTypes.Add(shipcallType); else first = false; } this.comboBoxArrivalBerth.ItemsSource = BreCalLists.Berths; this.comboBoxDepartureBerth.ItemsSource = BreCalLists.Berths; this.comboBoxTimeRef.ItemsSource = BreCalLists.TimeRefs; this.comboBoxHarbour.ItemsSource = BreCalLists.Ports; this.integerUpDownShiftingCount.Value = this.ShipcallModel.ShiftSequence; if (this.ShipcallModel.Shipcall == null) this.ShipcallModel.Shipcall = new(); this.CopyToControls(); this.EnableControls(); } private void buttonOK_Click(object sender, RoutedEventArgs e) { this.CopyToModel(); this.DialogResult = true; this.Close(); } private void buttonCancel_Click(object sender, RoutedEventArgs e) { this.DialogResult= false; this.Close(); } private void comboBoxShip_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (this.comboBoxShip.SelectedItem != null) { ShipModel? ship = this.comboBoxShip.SelectedItem as ShipModel; this.integerUpDownIMO.Value = ship?.Ship.Imo; this.textBoxCallsign.Text = ship?.Ship.Callsign; this.doubleUpDownLength.Value = ship?.Ship.Length; this.doubleUpDownWidth.Value = ship?.Ship.Width; } else { this.integerUpDownIMO.Value = null; this.textBoxCallsign.Text = string.Empty; this.doubleUpDownLength.Value = null; this.doubleUpDownWidth.Value = null; } this.CheckForCompletion(); } private void comboBoxAgency_SelectionChanged(object sender, SelectionChangedEventArgs e) { this.EnableControls(); this.CheckForCompletion(); } private void comboBoxCategories_SelectionChanged(object? sender, SelectionChangedEventArgs? e) { ShipcallType? type = GetShipcallTypeFromCombobox(); if (type != null) { switch (type) { case ShipcallType.Arrival: this.datePickerETD.Visibility = Visibility.Hidden; this.labelETD.Visibility = Visibility.Hidden; this.datePickerETA.Visibility = Visibility.Visible; this.labelETA.Visibility = Visibility.Visible; Grid.SetRow(datePickerETA, 3); Grid.SetRow(labelETA, 3); this.datePickerETD.Value = null; this.comboBoxDepartureBerth.SelectedIndex = -1; this.comboBoxDepartureBerth.IsEnabled = false; this.comboBoxArrivalBerth.IsEnabled = true; this.comboBoxTimeRef.IsEnabled = true; this.labelShiftingCount.Visibility = Visibility.Hidden; this.integerUpDownShiftingCount.Visibility = Visibility.Hidden; break; case ShipcallType.Departure: this.datePickerETD.Visibility = Visibility.Visible; this.labelETD.Visibility = Visibility.Visible; this.datePickerETA.Visibility = Visibility.Hidden; this.labelETA.Visibility = Visibility.Hidden; this.datePickerETA.Value = null; this.comboBoxArrivalBerth.SelectedIndex = -1; this.comboBoxArrivalBerth.IsEnabled = false; this.comboBoxDepartureBerth.IsEnabled = true; this.comboBoxTimeRef.IsEnabled = false; this.comboBoxTimeRef.SelectedIndex = 0; this.labelShiftingCount.Visibility = Visibility.Hidden; this.integerUpDownShiftingCount.Visibility = Visibility.Hidden; break; case ShipcallType.Shifting: Grid.SetRow(datePickerETA, 4); Grid.SetRow(labelETA, 4); this.datePickerETA.Visibility = Visibility.Visible; this.labelETA.Visibility = Visibility.Visible; this.datePickerETD.Visibility = Visibility.Visible; this.labelETD.Visibility = Visibility.Visible; this.comboBoxArrivalBerth.IsEnabled = true; this.comboBoxDepartureBerth.IsEnabled = true; this.comboBoxTimeRef.IsEnabled = false; this.comboBoxTimeRef.SelectedIndex = 0; this.labelShiftingCount.Visibility = Visibility.Visible; this.integerUpDownShiftingCount.Visibility = Visibility.Visible; break; } } this.CheckForCompletion(); } #endregion #region Context menu handlers private void contextMenuItemClearAgency_Click(object sender, RoutedEventArgs e) { this.comboBoxAgency.SelectedIndex = -1; this.ShipcallModel.AssignedParticipants.Remove(Extensions.ParticipantType.AGENCY); } #endregion #region private methods ShipcallType? GetShipcallTypeFromCombobox() { EnumToStringConverter enumToStringConverter = new(); return (ShipcallType?)enumToStringConverter.ConvertBack(this.comboBoxCategories.SelectedItem, typeof(ShipcallType), new object(), System.Globalization.CultureInfo.CurrentCulture); } void CheckForCompletion() { bool isEnabled = true; isEnabled &= this.comboBoxShip.SelectedItem != null; isEnabled &= this.comboBoxCategories.SelectedItem != null; isEnabled &= this.comboBoxHarbour.SelectedItem != null; if (comboBoxCategories.SelectedItem == null) { isEnabled = false; } else { ShipcallType callType = GetShipcallTypeFromCombobox() ?? ShipcallType.Undefined; switch (callType) { case ShipcallType.Departure: isEnabled &= this.comboBoxDepartureBerth.SelectedItem != null; isEnabled &= this.datePickerETD.Value.HasValue; if(this.datePickerETD.Value.HasValue) isEnabled &= (this.datePickerETD.Value.Value > DateTime.Now); break; case ShipcallType.Arrival: isEnabled &= this.comboBoxArrivalBerth.SelectedItem != null; isEnabled &= this.datePickerETA.Value.HasValue; if(this.datePickerETA.Value.HasValue) isEnabled &= (this.datePickerETA.Value.Value > DateTime.Now); break; case ShipcallType.Shifting: isEnabled &= ((this.comboBoxDepartureBerth.SelectedItem != null) && (this.comboBoxArrivalBerth.SelectedItem != null)); isEnabled &= this.datePickerETD.Value.HasValue; isEnabled &= this.datePickerETA.Value.HasValue; if (this.datePickerETD.Value.HasValue) isEnabled &= (this.datePickerETD.Value.Value > DateTime.Now); if (this.datePickerETA.Value.HasValue) isEnabled &= (this.datePickerETA.Value.Value > DateTime.Now); break; } } isEnabled &= this.comboBoxAgency.SelectedItem != null; this.buttonOK.IsEnabled = isEnabled; } private void CopyToModel() { if (this.ShipcallModel.Shipcall != null) { this.ShipcallModel.Shipcall.Type = GetShipcallTypeFromCombobox() ?? ShipcallType.Undefined; this.ShipcallModel.Shipcall.Eta = this.datePickerETA.Value; this.ShipcallModel.Shipcall.Etd = this.datePickerETD.Value; this.ShipcallModel.Shipcall.ShipId = ((ShipModel)this.comboBoxShip.SelectedItem).Ship.Id; this.ShipcallModel.Ship = ((ShipModel)this.comboBoxShip.SelectedItem).Ship; this.ShipcallModel.Shipcall.Canceled = this.checkBoxCancelled.IsChecked; if (this.ShipcallModel.Shipcall.Type != ShipcallType.Shifting) // incoming, outgoing { this.ShipcallModel.Shipcall.ArrivalBerthId = (this.comboBoxArrivalBerth.SelectedItem != null) ? ((Berth)this.comboBoxArrivalBerth.SelectedItem).Id : null; this.ShipcallModel.Shipcall.DepartureBerthId = (this.comboBoxDepartureBerth.SelectedItem != null) ? ((Berth)this.comboBoxDepartureBerth.SelectedItem).Id : null; } else // shifting { this.ShipcallModel.Shipcall.DepartureBerthId = (this.comboBoxArrivalBerth.SelectedItem != null) ? ((Berth)this.comboBoxArrivalBerth.SelectedItem).Id : null; this.ShipcallModel.Shipcall.ArrivalBerthId = (this.comboBoxDepartureBerth.SelectedItem != null) ? ((Berth)this.comboBoxDepartureBerth.SelectedItem).Id : null; this.ShipcallModel.ShiftSequence = (byte?) this.integerUpDownShiftingCount.Value; } Participant? participant; participant = (Participant?)this.comboBoxAgency.SelectedItem; if (participant != null) { ParticipantAssignment pa = new() { ParticipantId = participant.Id, Type = (int)Extensions.ParticipantType.AGENCY }; this.ShipcallModel.AssignedParticipants[Extensions.ParticipantType.AGENCY] = pa; } else { // AGENCY was set before and now is set to nothing if (this.ShipcallModel.AssignedParticipants.ContainsKey(ParticipantType.AGENCY)) this.ShipcallModel.AssignedParticipants.Remove(ParticipantType.AGENCY); } // BSMD and port authority are always added // get port authority from berth int? berthId = this.ShipcallModel.Shipcall.ArrivalBerthId; berthId ??= this.ShipcallModel.Shipcall.DepartureBerthId; if (berthId != null) { Berth? selectedBerth = BreCalLists.Berths.Find((x) => x.Id == berthId); if (selectedBerth?.AuthorityId != null) { if (BreCalLists.ParticipantLookupDict.ContainsKey(selectedBerth.AuthorityId.Value)) { ParticipantAssignment pab = new() { ParticipantId = selectedBerth.AuthorityId.Value, Type = (int)ParticipantType.PORT_ADMINISTRATION }; this.ShipcallModel.AssignedParticipants[ParticipantType.PORT_ADMINISTRATION] = pab; } } ParticipantAssignment pa = new() { ParticipantId = App.Participant.Id, Type = (int)ParticipantType.BSMD }; this.ShipcallModel.AssignedParticipants[ParticipantType.BSMD] = pa; } // set the time reference value (which point do all times refer to?) this.ShipcallModel.Shipcall.TimeRefPoint = this.comboBoxTimeRef.SelectedIndex; this.ShipcallModel.Shipcall.PortId = ((Port) this.comboBoxHarbour.SelectedItem).Id; } } private void CopyToControls() { if (this.ShipcallModel == null) return; if (this.ShipcallModel.Shipcall != null) { this.comboBoxTimeRef.SelectedIndex = this.ShipcallModel.Shipcall.TimeRefPoint ?? 1; this.comboBoxCategories.SelectedItem = new EnumToStringConverter().Convert(this.ShipcallModel.Shipcall.Type, typeof(ShipcallType), new object(), System.Globalization.CultureInfo.CurrentCulture); if (this.ShipcallModel.Shipcall.Eta != DateTime.MinValue) this.datePickerETA.Value = this.ShipcallModel.Shipcall.Eta; // this.textBoxVoyage.Text = this.ShipcallModel.Shipcall.Voyage; this.datePickerETD.Value = this.ShipcallModel.Shipcall.Etd; if (BreCalLists.Ships.Find(x => x.Ship.Id == this.ShipcallModel.Shipcall.ShipId) != null) { this.comboBoxShip.SelectedValue = this.ShipcallModel.Shipcall.ShipId; } else { this.comboBoxShip.IsEnabled = false; } this.checkBoxCancelled.IsChecked = this.ShipcallModel.Shipcall.Canceled ?? false; if (this.ShipcallModel.Shipcall.Type != ShipcallType.Shifting) // incoming, outgoing { this.comboBoxArrivalBerth.SelectedValue = this.ShipcallModel.Shipcall.ArrivalBerthId; this.comboBoxDepartureBerth.SelectedValue = this.ShipcallModel.Shipcall.DepartureBerthId; } else // shifting { this.comboBoxArrivalBerth.SelectedValue = this.ShipcallModel.Shipcall.DepartureBerthId; this.comboBoxDepartureBerth.SelectedValue = this.ShipcallModel.Shipcall.ArrivalBerthId; } if (this.ShipcallModel.Shipcall.Participants == null) this.ShipcallModel.Shipcall.Participants = new(); if(this.ShipcallModel.AssignedParticipants.ContainsKey(ParticipantType.AGENCY)) { if (BreCalLists.ParticipantLookupDict.ContainsKey(this.ShipcallModel.AssignedParticipants[ParticipantType.AGENCY].ParticipantId)) { this.comboBoxAgency.SelectedValue = this.ShipcallModel.AssignedParticipants[ParticipantType.AGENCY].ParticipantId; } } if (BreCalLists.PortLookupDict.ContainsKey(this.ShipcallModel.Shipcall.PortId)) this.comboBoxHarbour.SelectedValue = this.ShipcallModel.Shipcall.PortId; } } private void EnableControls() { bool isBsmd = App.Participant.IsTypeFlagSet(ParticipantType.BSMD); bool isAgency = App.Participant.IsTypeFlagSet(ParticipantType.AGENCY); bool editRightGrantedForBSMD = false; // Special case: Selected Agency allows BSMD to edit their fields if (this.comboBoxAgency.SelectedIndex >= 0) { int agencyParticipantId = (int)this.comboBoxAgency.SelectedValue; Participant? p = BreCalLists.Participants.Find(x => x.Id == agencyParticipantId); if (p != null) { if(p.IsFlagSet(ParticipantFlag.ALLOW_BSMD) && isBsmd) isAgency = true; if(p.IsFlagSet(ParticipantFlag.ALLOW_BSMD)) editRightGrantedForBSMD = true; } } this.comboBoxAgency.IsEnabled = isBsmd; this.comboBoxArrivalBerth.IsEnabled = isBsmd || isAgency; this.comboBoxCategories.IsEnabled = isBsmd; this.comboBoxDepartureBerth.IsEnabled = isBsmd || isAgency; this.comboBoxShip.IsEnabled = isBsmd; this.datePickerETA.IsEnabled = isAgency || isBsmd; this.datePickerETD.IsEnabled = isAgency || isBsmd; this.labelBSMDGranted.Visibility = editRightGrantedForBSMD ? Visibility.Visible : Visibility.Hidden; this.comboBoxCategories_SelectionChanged(null, null); } #endregion #region control event handlers private void datePickerETA_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { this.CheckForCompletion(); } private void datePickerETD_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { this.CheckForCompletion(); } private void comboBoxArrivalBerth_SelectionChanged(object sender, SelectionChangedEventArgs e) { this.CheckForCompletion(); } private void comboBoxDepartureBerth_SelectionChanged(object sender, SelectionChangedEventArgs e) { this.CheckForCompletion(); } private void buttonEditShips_Click(object sender, RoutedEventArgs e) { ShipListDialog shipListDialog = new() { ShipApi = this.ShipApi }; shipListDialog.ShowDialog(); // reload combobox this.comboBoxShip.ItemsSource = null; this.comboBoxShip.ItemsSource = BreCalLists.Ships; } private void comboBoxHarbour_SelectionChanged(object sender, SelectionChangedEventArgs e) { Port port = (Port)this.comboBoxHarbour.SelectedItem; if (port == null) return; // Filter berth selection combobox by port List availableBerths = BreCalLists.GetBerthsByPort(port.Id); this.comboBoxArrivalBerth.ItemsSource = null; this.comboBoxArrivalBerth.ItemsSource = availableBerths; this.comboBoxDepartureBerth.ItemsSource = null; this.comboBoxDepartureBerth.ItemsSource = availableBerths; // Filter agency combobox by port List availableAgencies = BreCalLists.GetParticipants(port.Id, ParticipantType.AGENCY); this.comboBoxAgency.ItemsSource = null; this.comboBoxAgency.ItemsSource = availableAgencies; } #endregion } }