using BS.Shared.DataContracts; using BS.Shared; using BS.Shared.DataContracts.Feature.AI; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using BeWo.ViewModel.ListViewModel; using System.Windows.Input; using BS.Shared.Core; using DevExpress.Mvvm; using BeWo.ServiceProxy; using BS.Shared.Extensions; namespace BeWo.ViewModel.View { public class AiConversationChatViewModel : AbstractBaseVM { private bool _IsSettingsOpen; private bool _IsCloneOpen; private bool _IsSending; private string _MessageInput; private string _ContextInput; private AiModelDC _SelectedModel; private AiConfigVM _Config; public AiConversationChatViewModel() { Models = new ObservableSortCollection(); SendNewMessageCommand = new DelegateCommand(SendNewMessage, () => ListVM.SelectedVM is object && !string.IsNullOrWhiteSpace(MessageInput) && !IsSending); OpenNewConversationCommand = new DelegateCommand(OpenNewConversation, () => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleChatAdd)); StartConversationWithMessageCommand = new DelegateCommand(StartConversationWithMessage, () => !string.IsNullOrWhiteSpace(MessageInput) && !IsSending); ReloadConfigCommand = new DelegateCommand(ReloadConfig); ReloadConversationsCommand = new DelegateCommand(ReloadConversations); ReloadModelsCommand = new DelegateCommand(ReloadModels); OpenSettingCommand = new DelegateCommand(OpenSetting, () => (BeWoApp.AppSettings?.ModuleAiSettingsEnabled ?? true) && BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleViewSetting)); RenameCommand = new DelegateCommand(Rename, () => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleChatEdit) && ListVM.SelectedVM is object); OpenCloneCommand = new DelegateCommand(OpenClone, () => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleChatClone) && ListVM.SelectedVM is object); CloneCommand = new DelegateCommand(Clone); AskDeleteCommand = new DelegateCommand(AskDelete, () => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleChatDelete) && ListVM.SelectedVM is object); ListVM = new AiConversationListVM(); ListVM.SelectedVMChanged += (s, e) => FirePropertyChanged(nameof(IsNewConversationVisible)); } public event EventHandler SendNewMessageSuccess; public ICommand SendNewMessageCommand { get; set; } public ICommand OpenNewConversationCommand { get; set; } public ICommand StartConversationWithMessageCommand { get; set; } public ICommand RequestNewConversationCommand { get; set; } public ICommand TestCommand { get; set; } public ICommand AskDeleteCommand { get; set; } public ICommand ReloadConfigCommand { get; set; } public ICommand ReloadConversationsCommand { get; set; } public ICommand ReloadModelsCommand { get; set; } public ICommand OpenSettingCommand { get; set; } public ICommand RenameCommand { get; set; } public ICommand OpenCloneCommand { get; set; } public ICommand CloneCommand { get; set; } public AiConversationListVM ListVM { get; set; } public ObservableCollection Models { get; set; } public AiModelDC SelectedModel { get { return _SelectedModel; } set { if (_SelectedModel == value) return; _SelectedModel = value; FirePropertyChanged(nameof(SelectedModel)); } } public AiConfigVM Config { get { return _Config; } set { if (Config == value) return; _Config = value; FirePropertyChanged(nameof(Config)); } } public string MessageInput { get { return _MessageInput; } set { if (MessageInput == value) return; _MessageInput = value; FirePropertyChanged(nameof(MessageInput)); } } public string ContextInput { get { return _ContextInput; } set { if (ContextInput == value) return; _ContextInput = value; FirePropertyChanged(nameof(ContextInput)); } } public bool IsSettingsOpen { get => _IsSettingsOpen; set { _IsSettingsOpen = value; FirePropertyChanged(nameof(IsSettingsOpen)); } } public bool IsCloneOpen { get => _IsCloneOpen; set { _IsCloneOpen = value; FirePropertyChanged(nameof(IsCloneOpen)); } } public bool IsSending { get => _IsSending; set { _IsSending = value; FirePropertyChanged(nameof(IsSending)); } } public bool IsNewConversationVisible => ListVM.SelectedVM is null; public AiContextType UIContext { get; set; } public long? ReferenceObjectOid { get; set; } public Dictionary ContextBeWoObjects { get; set; } private void StartConversationWithMessage() { StartSending(); try { var message = MessageInput; var conv = new AiConversationDC(); conv.Created = DateTime.Now; conv.Updated = DateTime.Now; conv.UIContext = UIContext; conv.ContextBeWoObjects = ContextBeWoObjects; conv.Messages = new List() { new AiConversationMessageDC() { Message = message, Role = AiConversationMessageRole.User } }; var vm = InsertConverstion(conv); ServiceFacade.DoAiEnhancedServiceAsnyc( x => x.CreateAiConversationWithMessage(conv, Config.SelectedModel.Oid.Value, message), dc => UpdateConverstion(vm, dc), e => { EndSending(); ListVM.VMList.Remove(vm); } ); } catch (Exception ex) { EndSending(); } } private void OpenNewConversation() { ListVM.SelectedVM = null; } private void SendNewMessage() { StartSending(); try { var conv = ListVM.SelectedVM; var msg_dc = new AiConversationMessageDC(); msg_dc.Message = MessageInput; msg_dc.Role = BS.Shared.AiConversationMessageRole.User; msg_dc.Created = DateTime.Now; var msg_vm = new AiConversationMessageVM(msg_dc); conv.Messages.VMList.Add(msg_vm); ServiceFacade.DoAiEnhancedServiceAsnyc( x => x.SendNewMessage(conv.DataContract.Oid.Value, MessageInput), (messages) => { if (messages.Count != 2) throw new InvalidOperationException("message count: " + messages.Count); msg_vm.DataContract = messages[0]; conv.Messages.VMList.Add(new AiConversationMessageVM(messages[1])); MessageInput = string.Empty; EndSending(); SendNewMessageSuccess?.Invoke(this, EventArgs.Empty); }, (exception) => { conv.Messages.VMList.Remove(msg_vm); EndSending(); } ); } catch (Exception ex) { EndSending(); } } private void StartSending() { if (IsSending) throw new InvalidOperationException("Sendet bereits"); IsSending = true; } private void EndSending() { if (!IsSending) throw new InvalidOperationException("Sendet nicht"); IsSending = false; } private AiConversationVM InsertConverstion(AiConversationDC dc) { var vm = new AiConversationVM(dc); ListVM.VMList.Insert(0, vm); ListVM.SelectedVM = vm; return vm; } private void UpdateConverstion(AiConversationVM vm, AiConversationDC dc) { vm.UpdateByDataContract(dc); MessageInput = string.Empty; EndSending(); SendNewMessageSuccess?.Invoke(this, EventArgs.Empty); } private void ReloadConfig() { ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.GetAiConfig(), (x) => { if (Config is null) Config = new AiConfigVM(x); else Config.Update(x); }); } public void UpdateConfig() { if (!Config.IsDirty) return; ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiConfig(Config.CommitToDataContract()), (x) => { Config.Update(x); }); } private void ReloadModels() { ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.GetAiModels(), (x) => { Models.MakeEqualTo(x); if (Config.SelectedModel is null && Models.Any()) Config.SelectedModel = Models.First(); }); } private void ReloadConversations() { var ui_context = UIContext; var reference = ReferenceObjectOid; VMFactory.CreateAiConversationListVM(ui_context, reference, (listvm) => { ListVM.VMList.MakeEqualTo(listvm.VMList); }); } private void OpenSetting() { ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.GetAiModels(), (x) => { Models.MakeEqualTo(x); IsSettingsOpen = true; }); } private void Rename() { if(ListVM.SelectedVM is AiConversationVM vm) { vm.IsEditing = !vm.IsEditing; } } private void OpenClone() { foreach (var message in ListVM.SelectedVM.Messages.VMList) { message.SetIsChecked(true); } IsCloneOpen = true; } private void Clone() { var conv = ListVM.SelectedVM; AiConversationMessageVM last = null; foreach (var msg in conv.Messages.VMList) { if (!msg.IsChecked) break; last = msg; } var conv_oid = conv.DataContract.Oid.Value; var msg_oid = last?.DataContract.Oid; ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.CloneAiConversation(conv_oid, msg_oid), dc => { InsertConverstion(dc); CloseClone(); }); } private void CloseClone() { IsCloneOpen = false; } public void AskDelete() { var selected = ListVM.SelectedVM; var info = selected.Displayname; var oid = selected.DataContract.Oid; if (BeWoAppInfo.IsInAiSandboxMode) { info += $":{oid}"; } var msg = $"Wollen Sie die ausgewählte Konversation ({info}) löschen?"; if (MessageBox.Show(msg, "Konversation löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) { ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.DeleteAiConversation(oid.Value), () => { ListVM.VMList.Remove(selected); CommandManager.InvalidateRequerySuggested(); //SelectedVM = VMList.FirstOrDefault(); }); } } } }