// Copyright (c) 2023 schick Informatik // Description: Container model for shipcall related info // using BreCalClient.misc.Api; using BreCalClient.misc.Model; using System; using System.Collections.Generic; namespace BreCalClient { /// /// Container model to aggregate separate models for the Shipcall control data binding /// public class ShipcallControlModel { #region Enumerations public enum TrafficLightMode { OFF, GREEN, YELLOW, RED, RED_YELLOW, ALL }; [Flags] public enum StatusFlags { RED, GREEN, YELLOW, BLINK_1, BLINK_2 }; #endregion #region Properties public Shipcall? Shipcall { get; set; } public Ship? Ship { get; set; } public string? Berth { get; set; } internal Dictionary AssignedParticipants { get; } = new(); public List Times { get; set; } = new(); public DateTime? Eta { get { Times? agencyTimes = this.GetTimesForParticipantType(ParticipantType.AGENCY); if((agencyTimes != null) && (agencyTimes.EtaBerth != null)) return agencyTimes.EtaBerth; return Shipcall?.Eta; } } public DateTime? Etd { get { Times? agencyTimes = this.GetTimesForParticipantType(Extensions.ParticipantType.AGENCY); if ((agencyTimes != null) && (agencyTimes.EtdBerth != null)) return agencyTimes.EtdBerth; return Shipcall?.Etd; } } public TrafficLightMode LightMode { get { TrafficLightMode tlm = TrafficLightMode.OFF; if (this.Shipcall != null) { if(this.Shipcall.Evaluation.HasValue) { tlm = (TrafficLightMode)this.Shipcall.Evaluation; } } return tlm; } } public string Title { get { if (this.Shipcall == null) return ""; Extensions.TypeEnum callType = (Extensions.TypeEnum) this.Shipcall.Type; return string.Format("{0} {1}", callType, this.Ship?.Name); } } #endregion #region public methods public void AssignParticipants() { this.AssignedParticipants.Clear(); if (Shipcall != null) { foreach (ParticipantAssignment participantAssignment in Shipcall.Participants) { AssignedParticipants[(ParticipantType)participantAssignment.Type] = participantAssignment; } } } internal Times? GetTimesForParticipantType(ParticipantType type) { if (AssignedParticipants.ContainsKey(type)) { int participantId = AssignedParticipants[type].ParticipantId; foreach (Times times in this.Times) { if ((times.ParticipantId == participantId) && (times.ParticipantType == (int) type)) return times; } if(type == ParticipantType.AGENCY) { // if I am BSMD and no agency entry was found this means we are editing the agency entry if(App.Participant.Type == (int) ParticipantType.BSMD) { foreach(Times times in this.Times) { if ((times.ParticipantId == App.Participant.Id) && (times.ParticipantType == (int) ParticipantType.AGENCY)) return times; } } } } return null; } public bool ContainsRemarkText(string text) { if(Shipcall != null) { foreach(Times times in this.Times) { if (times.Remarks == null) continue; if(times.Remarks.Contains(text)) return true; } } return false; } public string? GetBerthText(Times times) { string? berthText = null; if ((BreCalLists.Berths != null) && times.BerthId.HasValue && (this.Shipcall?.Type != ShipcallType.Shifting)) { Berth? berth = BreCalLists.AllBerths.Find((x) => x.Id == times.BerthId); berthText = berth?.Name; } if ((berthText == null) && (times.ParticipantType != ParticipantType.TERMINAL)) { if (this.Shipcall?.Type == ShipcallType.Arrival) { Berth? berth = BreCalLists.AllBerths?.Find((x) => x.Id == this.Shipcall?.ArrivalBerthId); berthText = berth?.Name; } else { Berth? berth = BreCalLists.AllBerths?.Find((x) => x.Id == this.Shipcall?.DepartureBerthId); berthText = berth?.Name; } } return berthText; } /// /// After closing the edit shipcall or edit agency dialogs, the times assignments may have changed. /// This function updates the assignments for existing times records accordingly and saves them. /// /// API reference to PUT eidted times internal async void UpdateTimesAssignments(DefaultApi _api) { foreach (ParticipantType participantType in this.AssignedParticipants.Keys) { Times? times = this.GetTimesForParticipantType(participantType); if(times == null) continue; if(times.ParticipantId != this.AssignedParticipants[participantType].ParticipantId) { times.ParticipantId = this.AssignedParticipants[participantType].ParticipantId; await _api.TimesPutAsync(times); } } // if somebody just removed an assignment it is gone fom AssignedParticipants, but there is still a // times record left which must be removed List deleteTimes = new(); foreach (Times times in this.Times) { bool foundTimes = false; foreach (ParticipantAssignment pa in this.AssignedParticipants.Values) { if((pa.ParticipantId == times.ParticipantId) && (pa.Type == times.ParticipantType)) { foundTimes = true; break; } } if (!foundTimes) { deleteTimes.Add(times); } } foreach(Times times in deleteTimes) { _api.TimesDelete(times.Id); this.Times.Remove(times); } } #endregion #region helper internal Participant? GetParticipantForType(Extensions.ParticipantType participantType) { if(AssignedParticipants.ContainsKey(participantType) && BreCalLists.ParticipantLookupDict.ContainsKey(AssignedParticipants[participantType].ParticipantId)) return BreCalLists.ParticipantLookupDict[AssignedParticipants[participantType].ParticipantId]; return null; } private bool IsFlagSet(StatusFlags flag) { if(this.Shipcall == null) return false; return (this.Shipcall.Flags & (int) flag) != 0; } #endregion } }