using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using System.Windows.Input; namespace XLAB2 { internal sealed class FrpdDirectoryWindowViewModel : ObservableObject { private readonly IFrpdDirectoryDialogService _dialogService; private readonly FrpdDirectoryService _service; private List _frpdCache; private bool _isBusy; private string _searchText; private FrpdDirectoryItem _selectedFrpd; private FrpdvdDirectoryItem _selectedFrpdvd; private string _statusText; public FrpdDirectoryWindowViewModel(FrpdDirectoryService service, IFrpdDirectoryDialogService dialogService) { _service = service; _dialogService = dialogService; _frpdCache = new List(); FrpdItems = new ObservableCollection(); FrpdvdItems = new ObservableCollection(); AddFrpdCommand = new RelayCommand(delegate { AddFrpdAsync(); }, delegate { return !IsBusy; }); EditFrpdCommand = new RelayCommand(delegate { EditFrpdAsync(); }, delegate { return !IsBusy && SelectedFrpd != null; }); DeleteFrpdCommand = new RelayCommand(delegate { DeleteFrpdAsync(); }, delegate { return !IsBusy && SelectedFrpd != null; }); AddFrpdvdCommand = new RelayCommand(delegate { AddFrpdvdAsync(); }, delegate { return !IsBusy && SelectedFrpd != null; }); EditFrpdvdCommand = new RelayCommand(delegate { EditFrpdvdAsync(); }, delegate { return !IsBusy && SelectedFrpdvd != null; }); DeleteFrpdvdCommand = new RelayCommand(delegate { DeleteFrpdvdAsync(); }, delegate { return !IsBusy && SelectedFrpdvd != null; }); RefreshCommand = new RelayCommand(delegate { RefreshAsync(); }, delegate { return !IsBusy; }); UpdateStatus(); } public ICommand AddFrpdCommand { get; private set; } public ICommand AddFrpdvdCommand { get; private set; } public ICommand DeleteFrpdCommand { get; private set; } public ICommand DeleteFrpdvdCommand { get; private set; } public ICommand EditFrpdCommand { get; private set; } public ICommand EditFrpdvdCommand { get; private set; } public ObservableCollection FrpdItems { get; private set; } public ObservableCollection FrpdvdItems { get; private set; } public ICommand RefreshCommand { get; private set; } public bool IsBusy { get { return _isBusy; } private set { if (SetProperty(ref _isBusy, value)) { RaiseCommandStates(); } } } public string SearchText { get { return _searchText; } set { if (SetProperty(ref _searchText, value)) { ApplySearchFilter(); UpdateStatus(); } } } public FrpdDirectoryItem SelectedFrpd { get { return _selectedFrpd; } set { if (SetProperty(ref _selectedFrpd, value)) { RaiseCommandStates(); LoadFrpdvdForSelection(); UpdateStatus(); } } } public FrpdvdDirectoryItem SelectedFrpdvd { get { return _selectedFrpdvd; } set { if (SetProperty(ref _selectedFrpdvd, value)) { RaiseCommandStates(); UpdateStatus(); } } } public string StatusText { get { return _statusText; } private set { SetProperty(ref _statusText, value); } } public async Task InitializeAsync() { await ExecuteBusyOperationAsync(async delegate { await RefreshFrpdCoreAsync(null, null); }); } private void AddFrpdAsync() { var result = _dialogService.ShowFrpdEditDialog(new FrpdDirectoryItem(), true, _frpdCache.ToList(), _service); if (result == null) { return; } RunMutationOperation(async delegate { var createdId = await Task.Run(delegate { return _service.AddFrpdItem(result); }); await RefreshFrpdCoreAsync(createdId, null); _dialogService.ShowInfo("Запись FRPD добавлена."); }); } private void AddFrpdvdAsync() { if (SelectedFrpd == null) { return; } var result = _dialogService.ShowFrpdvdEditDialog(new FrpdvdDirectoryItem { FrpdId = SelectedFrpd.Id }, true, FrpdvdItems.ToList(), _service); if (result == null) { return; } RunMutationOperation(async delegate { var createdId = await Task.Run(delegate { return _service.AddFrpdvdItem(result); }); await RefreshFrpdCoreAsync(result.FrpdId, createdId); _dialogService.ShowInfo("Запись FRPDVD добавлена."); }); } private void ApplyFrpdFilter(int? preferredId) { var filteredItems = _frpdCache.Where(delegate(FrpdDirectoryItem item) { return MatchesSearch(item); }).ToList(); FrpdItems.Clear(); foreach (var item in filteredItems) { FrpdItems.Add(item); } SelectedFrpd = preferredId.HasValue ? FrpdItems.FirstOrDefault(delegate(FrpdDirectoryItem item) { return item.Id == preferredId.Value; }) : FrpdItems.FirstOrDefault(); } private void ApplySearchFilter() { if (!IsBusy) { ApplyFrpdFilter(SelectedFrpd == null ? (int?)null : SelectedFrpd.Id); } } private static FrpdDirectoryItem CloneFrpd(FrpdDirectoryItem source) { return new FrpdDirectoryItem { CreatedOn = source.CreatedOn, Guid = source.Guid, Id = source.Id, LiquidatedOn = source.LiquidatedOn, LocalCode = source.LocalCode, Name = source.Name, ParentId = source.ParentId, ParentName = source.ParentName }; } private static FrpdvdDirectoryItem CloneFrpdvd(FrpdvdDirectoryItem source) { return new FrpdvdDirectoryItem { ActivityId = source.ActivityId, ActivityName = source.ActivityName, FrpdId = source.FrpdId, Id = source.Id }; } private void DeleteFrpdAsync() { if (SelectedFrpd == null) { return; } var selected = SelectedFrpd; if (!_dialogService.Confirm(string.Format("Удалить организацию/подразделение \"{0}\"?", selected.Name))) { return; } RunMutationOperation(async delegate { var result = await Task.Run(delegate { return _service.DeleteFrpdItem(selected.Id); }); if (!result.IsDeleted) { _dialogService.ShowWarning(result.WarningMessage); return; } await RefreshFrpdCoreAsync(null, null); _dialogService.ShowInfo("Запись удалена."); }); } private void DeleteFrpdvdAsync() { if (SelectedFrpdvd == null) { return; } var selected = SelectedFrpdvd; if (!_dialogService.Confirm(string.Format("Удалить вид деятельности \"{0}\"?", selected.ActivityName))) { return; } RunMutationOperation(async delegate { var result = await Task.Run(delegate { return _service.DeleteFrpdvdItem(selected.Id); }); if (!result.IsDeleted) { _dialogService.ShowWarning(result.WarningMessage); return; } await RefreshFrpdCoreAsync(selected.FrpdId, null); _dialogService.ShowInfo("Запись удалена."); }); } private async Task ExecuteBusyOperationAsync(Func operation) { try { IsBusy = true; await operation(); } catch (Exception ex) { _dialogService.ShowError(ex.Message); } finally { IsBusy = false; } } private async Task ExecuteMutationOperationAsync(Func operation) { try { IsBusy = true; await operation(); } catch (InvalidOperationException ex) { _dialogService.ShowWarning(ex.Message); } catch (Exception ex) { _dialogService.ShowError(ex.Message); } finally { IsBusy = false; } } private void EditFrpdAsync() { if (SelectedFrpd == null) { return; } var result = _dialogService.ShowFrpdEditDialog(CloneFrpd(SelectedFrpd), false, _frpdCache.ToList(), _service); if (result == null) { return; } RunMutationOperation(async delegate { await Task.Run(delegate { _service.UpdateFrpdItem(result); }); await RefreshFrpdCoreAsync(result.Id, SelectedFrpdvd == null ? (int?)null : SelectedFrpdvd.Id); _dialogService.ShowInfo("Запись обновлена."); }); } private void EditFrpdvdAsync() { if (SelectedFrpdvd == null) { return; } var result = _dialogService.ShowFrpdvdEditDialog(CloneFrpdvd(SelectedFrpdvd), false, FrpdvdItems.ToList(), _service); if (result == null) { return; } RunMutationOperation(async delegate { await Task.Run(delegate { _service.UpdateFrpdvdItem(result); }); await RefreshFrpdCoreAsync(result.FrpdId, result.Id); _dialogService.ShowInfo("Запись обновлена."); }); } private string[] GetSearchTokens() { return (SearchText ?? string.Empty) .Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) .Select(delegate(string token) { return token.Trim().ToUpperInvariant(); }) .Where(delegate(string token) { return token.Length > 0; }) .ToArray(); } private void LoadFrpdvdForSelection() { if (!IsBusy) { RunBusyOperation(async delegate { if (SelectedFrpd == null) { FrpdvdItems.Clear(); SelectedFrpdvd = null; UpdateStatus(); return; } await RefreshFrpdvdCoreAsync(SelectedFrpd.Id, null); }); } } private bool MatchesSearch(FrpdDirectoryItem item) { if (item == null) { return false; } var tokens = GetSearchTokens(); if (tokens.Length == 0) { return true; } var haystack = string.Join( " ", new[] { item.Id.ToString(), item.Name, item.ParentName, item.LocalCode, item.Guid, item.ActivityNames } .Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })) .ToUpperInvariant(); return tokens.All(delegate(string token) { return haystack.IndexOf(token, StringComparison.Ordinal) >= 0; }); } private async Task RefreshFrpdCoreAsync(int? frpdIdToSelect, int? frpdvdIdToSelect) { var currentFrpdId = SelectedFrpd == null ? (int?)null : SelectedFrpd.Id; _frpdCache = (await Task.Run(delegate { return _service.LoadFrpdItems(); })).ToList(); ApplyFrpdFilter(frpdIdToSelect.HasValue ? frpdIdToSelect : currentFrpdId); if (SelectedFrpd == null) { FrpdvdItems.Clear(); SelectedFrpdvd = null; UpdateStatus(); return; } await RefreshFrpdvdCoreAsync(SelectedFrpd.Id, frpdvdIdToSelect); UpdateStatus(); } private async Task RefreshFrpdvdCoreAsync(int frpdId, int? frpdvdIdToSelect) { var items = await Task.Run(delegate { return _service.LoadFrpdvdItems(frpdId); }); FrpdvdItems.Clear(); foreach (var item in items) { FrpdvdItems.Add(item); } SelectedFrpdvd = frpdvdIdToSelect.HasValue ? FrpdvdItems.FirstOrDefault(delegate(FrpdvdDirectoryItem item) { return item.Id == frpdvdIdToSelect.Value; }) : FrpdvdItems.FirstOrDefault(); UpdateStatus(); } private void RaiseCommandStates() { ((RelayCommand)AddFrpdCommand).RaiseCanExecuteChanged(); ((RelayCommand)EditFrpdCommand).RaiseCanExecuteChanged(); ((RelayCommand)DeleteFrpdCommand).RaiseCanExecuteChanged(); ((RelayCommand)AddFrpdvdCommand).RaiseCanExecuteChanged(); ((RelayCommand)EditFrpdvdCommand).RaiseCanExecuteChanged(); ((RelayCommand)DeleteFrpdvdCommand).RaiseCanExecuteChanged(); ((RelayCommand)RefreshCommand).RaiseCanExecuteChanged(); } private void RefreshAsync() { RunBusyOperation(async delegate { await RefreshFrpdCoreAsync(SelectedFrpd == null ? (int?)null : SelectedFrpd.Id, SelectedFrpdvd == null ? (int?)null : SelectedFrpdvd.Id); }); } private async void RunBusyOperation(Func operation) { try { await ExecuteBusyOperationAsync(operation); } catch (Exception ex) { IsBusy = false; _dialogService.ShowError(ex.Message); } } private async void RunMutationOperation(Func operation) { try { await ExecuteMutationOperationAsync(operation); } catch (Exception ex) { IsBusy = false; _dialogService.ShowError(ex.Message); } } private void UpdateStatus() { var searchText = string.IsNullOrWhiteSpace(SearchText) ? null : SearchText.Trim(); StatusText = string.Format( "{0}Подразделений: {1}/{2}. Видов деятельности: {3}.", string.IsNullOrWhiteSpace(searchText) ? string.Empty : string.Format("Поиск: \"{0}\". ", searchText), FrpdItems.Count, _frpdCache.Count, FrpdvdItems.Count); } } }