public SettingsPageViewModel(PageManager pageManager, IReactiveFolderSettings settings)
			: base(pageManager)
		{
			Settings = settings;

			ReactionCheckInterval = new ReactiveProperty<string>(settings.DefaultMonitorIntervalSeconds.ToString());

			ReactionCheckInterval.Subscribe(x =>
			{
				settings.DefaultMonitorIntervalSeconds = int.Parse(x);
				settings.Save();
			});

			ReactionCheckInterval.SetValidateNotifyError(x => 
			{
				int temp;
				if (false == int.TryParse(x, out temp))
				{
					return "Number Only";
				}

				return null;
			});

		}
		public PageViewModelBase(PageManager pageManager, IFolderReactionMonitorModel monitor)
		{
			PageManager = pageManager;
			_MonitorModel = monitor;

			
		}
		public InstantActionPageViewModel(PageManager pageManager, IEventAggregator ea, IAppPolicyManager appPolicyManager, IInstantActionManager instantActionManager, IFolderReactionMonitorModel monitor, IHistoryManager historyManager)
			: base(pageManager)
		{
			_EventAggregator = ea;
			AppPolicyManger = appPolicyManager;
			InstantActionManager = instantActionManager;
			Monitor = monitor;
			HistoryManager = historyManager;

			InstantActionVM = new ReactiveProperty<InstantActionStepViewModel>();
				
		}
		public ReactionEditViewModelBase(PageManager pageManager, FolderReactionModel reactionModel)
		{
			PageManager = pageManager;
			Reaction = reactionModel;
			_CompositeDisposable = new CompositeDisposable();


			IsValid = new ReactiveProperty<bool>(false)
				.AddTo(_CompositeDisposable);

			ValidateState = IsValid
				.Select(x => x ? ValidationState.Valid : ValidationState.Invalid)
				.ToReactiveProperty(ValidationState.WaitFirstValidate)
				.AddTo(_CompositeDisposable);
		}
		public WorkFolderEditViewModel(PageManager pageManager, FolderReactionModel reactionModel)
			: base(pageManager, reactionModel)
		{

			Reaction.ObserveProperty(x => x.IsWorkFolderValid)
				.Subscribe(x => IsValid.Value = x)
				.AddTo(_CompositeDisposable);


			WorkFolderPath = Reaction.ObserveProperty(x => x.WorkFolder)
				.Select(x => x?.FullName ?? "<not selected>")
				.ToReactiveProperty()
				.AddTo(_CompositeDisposable);

		}
		public AppPolicyManagePageViewModel(PageManager pageManager, IAppPolicyManager appPolicyManager, IFolderReactionMonitorModel monitor)
			: base(pageManager)
		{
			Monitor = monitor;
			AppPolicyManager = appPolicyManager;
			AppPolicies = AppPolicyManager.Policies
				.ToReadOnlyReactiveCollection(x => new AppPolicyListItemViewModel(this, x));
			SelectedAppPolicy = new ReactiveProperty<AppPolicyListItemViewModel>();

			SelectedAppPolicy.Subscribe(x => 
			{
				if (x != null)
				{
					ShowAppPolicyEditPage(x.AppPolicy);
				}
			});
		}
		public ReactionEditPageViewModel(PageManager pageManager, IFolderReactionMonitorModel monitor, IAppPolicyManager appPolicyManager, IHistoryManager historyManager)
			: base(pageManager)
		{
			Monitor = monitor;
			_AppPolicyManager = appPolicyManager;
			HistoryManager = historyManager;

			_CompositeDisposable = new CompositeDisposable();

			ReactionVM = new ReactiveProperty<ReactionViewModel>()
				.AddTo(_CompositeDisposable);

			SaveCommand = new ReactiveCommand();

			SaveCommand.Subscribe(_ => Save())
				.AddTo(_CompositeDisposable);

		}
		public AboutPageViewModel(PageManager pageManager)
			: base(pageManager)
		{

			Tabs = new List<TabViewModelBase>();

			var aboutTabVM = new AboutTabViewModel();
			var howUseTabVM = new HowUseTabViewModel();
			var lisenceTabVM = new LisenceTabViewModel();
			Tabs.Add(aboutTabVM);
			Tabs.Add(howUseTabVM);
			Tabs.Add(lisenceTabVM);



			SelectedTab = new ReactiveProperty<TabViewModelBase>(aboutTabVM);

		}
		public ActionsEditViewModel(FolderReactionModel reactionModel, PageManager pageManager, IAppPolicyManager appPolicyManager)
			: base(pageManager, reactionModel)
		{
			_AppPolicyManager = appPolicyManager;

			Reaction.ObserveProperty(x => x.IsActionsValid)
				.Subscribe(x => IsValid.Value = x)
				.AddTo(_CompositeDisposable);


			// TODO: CollectionChangedをマージしてReactiveCollectionにする方法を使ってまとめる
			// Note: AppLaunchActionViewModelをAppOptionValueInstance1つずつに対して作成している
			Actions = new ObservableCollection<AppLaunchActionViewModel>(
				Reaction.Actions.Select(
					x =>
					{
						var appLaunchAction = x as AppLaunchReactiveAction;
						return new AppLaunchActionViewModel(this, Reaction, appLaunchAction);
					}
					)
				);

			Actions.CollectionChangedAsObservable()
				.Subscribe(itemPair => 
				{
					var onceRemoveItems = Reaction.Actions.ToArray();
					foreach (var onceRemoveItem in onceRemoveItems)
					{
						Reaction.RemoveAction(onceRemoveItem);
					}
					
					foreach(var reAdditem in Actions)
					{
						Reaction.AddAction(reAdditem.Action);
					}
				});

			IsActionsEmpty = Actions.ObserveProperty(x => x.Count)
				.Select(x => x == 0)
				.ToReactiveProperty();

			IsActionsEmpty.Subscribe();
		}
		public FilterEditViewModel(PageManager pageManager, FolderReactionModel reactionModel)
			: base(pageManager, reactionModel)
		{
			Reaction.ObserveProperty(x => x.IsFilterValid)
				.Subscribe(x => IsValid.Value = x)
				.AddTo(_CompositeDisposable);


			// 
			// Reactionが持っていないフィルターモデルは個々で作成する


			var currentFilterType = Reaction.Filter.OutputItemType;

			FileFilterViewModel fileFilterVM;
			FolderFilterViewModel folderFilterVM;

			if (currentFilterType == FolderItemType.File)
			{
				fileFilterVM = new FileFilterViewModel(Reaction, Reaction.Filter as FileReactiveFilter);
				folderFilterVM = new FolderFilterViewModel(Reaction, new FolderReactiveFilter());
			}
			else if (currentFilterType == FolderItemType.Folder)
			{
				fileFilterVM = new FileFilterViewModel(Reaction, new FileReactiveFilter());
				folderFilterVM = new FolderFilterViewModel(Reaction, Reaction.Filter as FolderReactiveFilter);
			}
			else
			{
				throw new Exception();
			}

			Filters = new List<FilterViewModelBase>();
			Filters.Add(fileFilterVM);
			Filters.Add(folderFilterVM);


			SelectedFilterVM = Reaction.ToReactivePropertyAsSynchronized(x => x.Filter,
				convert: (model) => Filters.Single(y => y.Filter == model),
				convertBack: (vm) => vm.Filter
				);
		}
		public HistoryPageViewModel(IHistoryManager histroyManager, PageManager pageManager, IFolderReactionMonitorModel monitor, IInstantActionManager instantActionManager)
			: base(pageManager)
		{
			HistoryManager = histroyManager;
			Monitor = monitor;
			InstantActionManager = instantActionManager;

			ShowHistoryVMs = new ObservableCollection<HistoryDataViewModel>();

			HistoryFileInfoList = new List<FileInfo>();

			CanIncrementalLoad = ShowHistoryVMs.CollectionChangedAsObservable()
				.Select(_ => HistoryFileInfoList.Count > ShowHistoryVMs.Count)
				.ToReactiveProperty();

			IncrementalLoadHistoryCommand = CanIncrementalLoad
				.ToReactiveCommand();

			IncrementalLoadHistoryCommand.Subscribe(_ => IncrementalLoadHistoryItems());
		}
		public DestinationEditViewModel(PageManager pageManager, FolderReactionModel reactionModel)
			: base(pageManager, reactionModel)
		{
			_CompositeDisposable = new CompositeDisposable();

			Destination = reactionModel.Destination as AbsolutePathReactiveDestination;

			Reaction.ObserveProperty(x => x.IsDestinationValid)
				.Subscribe(x => IsValid.Value = x)
				.AddTo(_CompositeDisposable);

			OutputNamePattern = reactionModel.Destination.ToReactivePropertyAsSynchronized(x => x.OutputNamePattern)
				.AddTo(_CompositeDisposable);


			OutputFolderPath = Destination.AbsoluteFolderPath;

			OutputPathSample = Observable.Merge(
					Destination.ObserveProperty(x => x.AbsoluteFolderPath).Where(x => false == String.IsNullOrWhiteSpace(x)).ToUnit(),
					Destination.ObserveProperty(x => x.OutputNamePattern).Throttle(TimeSpan.FromSeconds(0.75)).ToUnit(),
					Reaction.ObserveProperty(x => x.OutputType).ToUnit()
				)
				.Select(_ => Destination.TestRename())
				.Where(x => false == String.IsNullOrEmpty(x))
				.Select(x =>
				{
					if (Reaction.OutputType == ReactiveFolder.Models.Util.FolderItemType.Folder)
					{
						return Path.Combine(Destination.AbsoluteFolderPath, x);
					}
					else
					{
						return Path.Combine(Destination.AbsoluteFolderPath, x) + ".extention";
					}
				})
				.ToReadOnlyReactiveProperty()
				.AddTo(_CompositeDisposable);



		}
		public FolderReactionManagePageViewModel(PageManager pageManager, IFolderReactionMonitorModel monitor, IEventAggregator ea, IAppPolicyManager appPolicyManager, IHistoryManager historyManager, IReactiveFolderSettings settings)
			: base(pageManager)
		{
			Monitor = monitor;
			_EventAggregator = ea;
			AppPolicyManager = appPolicyManager;
			HistoryManager = historyManager;
			Settings = settings;



			CurrentFolder = new ReactiveProperty<ReactionManageFolderViewModel>();
			FolderStack = new ObservableCollection<ReactionManageFolderViewModel>();

			FolderStack.CollectionChangedAsObservable()
				.Subscribe(x => 
				{
					CurrentFolder.Value = FolderStack.Last();
				});

			FolderStack.Add(new ReactionManageFolderViewModel(this, Monitor.RootFolder));
		}
		public MainWindowViewModel(PageManager pageManager, IEventAggregator ea, IFolderReactionMonitorModel monitor, IRegionManager regionManagar)
		{
			PageManager = pageManager;
			_Monitor = monitor;
			_RegionManager = regionManagar;

			MessageRequest = new InteractionRequest<Notification>();

			_CompositeDisposable = new CompositeDisposable();


			var e = ea.GetEvent<PubSubEvent<TaskbarIconBalloonMessageEventPayload>>();
			e.Subscribe(x =>
			{
				MessageRequest.Raise(new Notification()
				{
					Title = x.Title,
					Content = x.Message
				});
			});

			IsOpenSubContent = PageManager
				.ObserveProperty(x => x.IsOpenSubContent)
				.ToReactiveProperty(false);

			IsOpenSideMenu = PageManager
				.ToReactivePropertyAsSynchronized(x => x.IsOpenSideMenu);




			NotificationSource = new NotificationsSource();

			var toastEvent = ea.GetEvent<PubSubEvent<ToastNotificationEventPayload>>();
			toastEvent.Subscribe(x =>
			{
				NotificationSource.Show(x.Message, x.Type);
			});
		}
		public ReactiveFolderApp(IEventAggregator ea)
		{
			PageManager = new PageManager(ea);

			// AppData
			var appDataSaveFolder = new DirectoryInfo(AppDataSaveFolder);
			if (false == appDataSaveFolder.Exists)
			{
				appDataSaveFolder.Create();
			}



			Settings = new ReactiveFolderSettings();

			LoadGlobalSettings();


			var appPolicySaveFolder = Path.Combine(Settings.SaveFolder, APP_POLICY_FOLDER_NAME);
			AppPolicyManager = InitializeAppLaunchAction(appPolicySaveFolder);

			var updateRecordSaveFolder = Path.Combine(Settings.SaveFolder, UPDATE_RECORD_FOLDER_NAME);
			UpdateRecordManager = InitializeFileUpdateRecordManager(updateRecordSaveFolder);

			var historySaveFolder = Path.Combine(Settings.SaveFolder, HISTORY_FOLDER_NAME);
			HistoryManager = new HistoryManager(historySaveFolder, Settings.HistoryAvailableStorageSizeMB);



			// Note: ReactionMonitorの前提条件
			// AppPolicy / UpdateRecord / HistoryManager
			var reactionSaveFolder = Path.Combine(Settings.SaveFolder, REACTION_FOLDER_NAME);
			ReactionMonitor = InitializeMonitorModel(reactionSaveFolder, HistoryManager);
			ReactionMonitor.DefaultInterval = TimeSpan.FromSeconds(Settings.DefaultMonitorIntervalSeconds);


			InstantActionManager = new InstantActionManager(AppPolicyManager);
			InstantActionManager.SaveFolder = Path.Combine(Settings.SaveFolder, INSTANT_ACTION_FOLDER_NAME);
			InstantActionManager.TempSaveFolder = Path.Combine(Settings.SaveFolder, INSTANT_ACTION_TEMP_FOLDER_NAME);

		}
		public SideMenuViewModel(PageManager page, IRegionManager regionManagar)
		{
			PageManager = page;
			_RegionManager = regionManagar;

			
			

			AppPolicyManageListItem = new MenuItemViewModel(AppPageType.AppPolicyManage)
			{
				Title = "App Policy List",
				Kind = PackIconKind.ViewList,
				MenuItemSelectedCommand = new DelegateCommand(() =>
				{
					PageManager.OpenPage(AppPageType.AppPolicyManage);
				})
			};

			ReactionManageListItem = new MenuItemViewModel(AppPageType.ReactionManage)
			{
				Title = "Manage Reaction",
				Kind = PackIconKind.Monitor,
				MenuItemSelectedCommand = new DelegateCommand(() =>
				{
					PageManager.OpenPage(AppPageType.ReactionManage);
				})
			};

			InstantActionListItem = new MenuItemViewModel(AppPageType.InstantAction)
			{
				Title = "Instant Action",
				Kind = PackIconKind.Run,
				MenuItemSelectedCommand = new DelegateCommand(() =>
				{
					PageManager.OpenPage(AppPageType.InstantAction);
				})
			};

			HistoryListItem = new MenuItemViewModel(AppPageType.History)
			{
				Title = "History",
				Kind = PackIconKind.History,
				MenuItemSelectedCommand = new DelegateCommand(() =>
				{
					PageManager.OpenPage(AppPageType.History);
				})
			};



			SettingsListItem = new MenuItemViewModel(AppPageType.Settings)
			{
				Title = "Settings",
				Kind = PackIconKind.Settings,
				MenuItemSelectedCommand = new DelegateCommand(() =>
				{
					PageManager.OpenPage(AppPageType.Settings);
				})
			};

			AboutListItem = new MenuItemViewModel(AppPageType.About)
			{
				Title = "About",
				Kind = PackIconKind.CommentQuestionOutline,
				MenuItemSelectedCommand = new DelegateCommand(() => 
				{
					PageManager.OpenPage(AppPageType.About);
				})
			};


			MenuItems = new List<MenuItemViewModel>()
			{
				AppPolicyManageListItem,
				InstantActionListItem,
				ReactionManageListItem,
				HistoryListItem,

				SettingsListItem,
				AboutListItem,
			};




			PageManager.ObserveProperty(x => x.PageType)
				.Subscribe(x =>
				{
					foreach(var nonSelectedItem in MenuItems.Where(y => y.PageType != x))
					{
						nonSelectedItem.IsSelected = false;
					}

					MenuItems.Single(y => y.PageType == x).IsSelected = true;
				});
				
				

		}		
		// Reactionmodelを受け取ってVMを生成する

		public ReactionViewModel(FolderReactionModel reaction, PageManager pageManager, IAppPolicyManager appPolicyManager)
		{
			_CompositeDisposable = new CompositeDisposable();
			Reaction = reaction;
			PageManager = pageManager;
			_AppPolicyManager = appPolicyManager;


			IsReactionValid = Reaction.ObserveProperty(x => x.IsValid)
				.ToReactiveProperty()
				.AddTo(_CompositeDisposable);

			ReactionWorkName = Reaction.ToReactivePropertyAsSynchronized(x => x.Name)
				.AddTo(_CompositeDisposable);

			WorkFolderEditVM = new WorkFolderEditViewModel(PageManager, Reaction);
			FilterEditVM = new FilterEditViewModel(PageManager, Reaction);
			ActionsEditVM = new ActionsEditViewModel(Reaction, PageManager, _AppPolicyManager);
			DestinationEditVM = new DestinationEditViewModel(PageManager, Reaction);


			EditVMList = new List<ReactionEditViewModelBase>()
			{
				WorkFolderEditVM,
				FilterEditVM,
				ActionsEditVM,
				DestinationEditVM
			};

			IsEnable = Reaction.ToReactivePropertyAsSynchronized(x => x.IsEnable)
				.AddTo(_CompositeDisposable);

			// see@ http://stackoverflow.com/questions/1833830/timespan-parse-time-format-hhmmss
			// https://msdn.microsoft.com/en-us/library/ee372286.aspx
			MonitorIntervalSeconds = Reaction.ToReactivePropertyAsSynchronized(
				x => x.CheckInterval
				, convert: (timespan) => ((int)timespan.TotalSeconds).ToString()
				, convertBack: (seconds) => TimeSpan.FromSeconds(int.Parse(seconds))
				, ignoreValidationErrorValue: true
			)
			.AddTo(_CompositeDisposable);

			MonitorIntervalSeconds.SetValidateNotifyError(text =>
			{
				int temp;
				if (false == int.TryParse(text, out temp))
				{
					return "Number Only";
				}

				return null;
			});

			


		}
		public PageViewModelBase(PageManager pageManager)
		{
			PageManager = pageManager;
		}
		public HistoryDataViewModel(HistoryPageViewModel pageVM, PageManager pageManager, IFolderReactionMonitorModel monitor, IInstantActionManager instantActionManager, HistoryData historyData)
		{
			PageVM = pageVM;
			PageManager = pageManager;
			Monitor = monitor;
			InstantActionManage = instantActionManager;
			HistoryData = historyData;

			Actions = HistoryData.Actions
				.Select(x => new HistoryActionViewModel(this, x))
				.ToList();

			Files = HistoryData.FileHistories
				.Select(x => new HistoryDataByFileViewModel(this, x))
				.ToList();

			TargetFileAmount = Files.Count;

			SuccessCount = Files.Where(x => x.IsSuccessed).Count();

			var fileName = Path.GetFileName(HistoryData.ActionSourceFilePath);
			if (fileName.EndsWith(FolderModel.REACTION_EXTENTION))
			{
				IsSourceReaction = true;
			}
			else if (fileName.EndsWith(".rfinstant.json"))
			{
				IsSourceInstantAction = true;
			}
			
		}