public AIDAction(AIDAdventuresContainer container, AIDungeonWrapper.Action action)
            {
                this.Action       = action;
                this.InnerActions = new List <AIDungeonWrapper.Action>();

                this.container = container;
            }
        public MainWindow()
        {
            FileStream filestream   = new FileStream("log.txt", FileMode.Create);
            var        streamwriter = new StreamWriter(filestream);

            streamwriter.AutoFlush = true;
            Console.SetOut(streamwriter);
            Console.SetError(streamwriter);

            Console.WriteLine(string.Format("[Log] Start: {0}", DateTime.Now));
            InitializeComponent();
            this.Title = string.Format("{0} {1}", this.Title, VersionStr);

            var chromeDriverPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "chromedriver.exe");

            if (!System.IO.File.Exists(chromeDriverPath))
            {
                Console.WriteLine("[Log] Cannot find chromedriver");
                var chromeVersion = string.Empty;
                try
                {
                    const string suffix   = @"Google\Chrome\Application\chrome.exe";
                    var          prefixes = new List <string> {
                        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
                    };
                    var programFiles    = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
                    var programFilesx86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
                    if (programFilesx86 != programFiles)
                    {
                        prefixes.Add(programFiles);
                    }
                    else
                    {
                        var programFilesDirFromReg = Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion", "ProgramW6432Dir", null) as string;
                        if (programFilesDirFromReg != null)
                        {
                            prefixes.Add(programFilesDirFromReg);
                        }
                    }

                    prefixes.Add(programFilesx86);
                    var path = prefixes.Distinct().Select(prefix => System.IO.Path.Combine(prefix, suffix)).FirstOrDefault(File.Exists);

                    if (!string.IsNullOrEmpty(path))
                    {
                        chromeVersion = FileVersionInfo.GetVersionInfo(path.ToString()).FileVersion;
                    }
                }catch (Exception e)
                {
                    Console.WriteLine("[ERROR] Cannot detect chrome version");
                }

                if (MessageBox.Show(string.Format(Properties.Resources.MessageBox_ChromeDriverMissing_Text, chromeVersion),
                                    Properties.Resources.MessageBox_ChromeDriverMissing_Caption, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                {
                    OpenURL(@"https://chromedriver.chromium.org/downloads");
                }
                System.Environment.Exit(-1);
            }

            this.model       = new MainWindowViewModel();
            this.DataContext = this.model;

            this.model.TranslateLanguage = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;

            UpdateColorPickerColorsFromViewModel();

            CloseSideMenu();

            this.actionsModels = new Dictionary <string, ActionsModel>();

            this.scenarioOptionModel = new ScenarioOptionModel();
            this.scenarioOptionsControl.ItemsSource = this.scenarioOptionModel.Options;

            //return;

            this.model.LoadingText = Properties.Resources.LoadingText_Initializing;
            this.model.ShowInputTranslateLoading = false;
            this.model.ShowInputLoading          = false;

            UpdateWriteMode(WriteMode.Say);

            actionTranslator = new Translator();
            actionTranslator.Run();
            inputTranslator = new Translator();
            inputTranslator.Run();

            actionContainer = new AIDAdventuresContainer(actionTranslator);
            actionContainer.OnActionsChanged += ActionContainer_OnActionsChanged;

            StartHooker();
        }
        private void ActionContainer_OnActionsChanged(string publicId, List <AIDAdventuresContainer.AIDAction> actions)
        {
            //Update action model
            Dispatcher.Invoke(() =>
            {
                lock (this.actionsModels)
                {
                    if (!this.actionsModels.ContainsKey(publicId))
                    {
                        this.actionsModels.Add(publicId, new ActionsModel());
                    }

                    var actionsModel = this.actionsModels[publicId];

                    actions.Sort();
                    foreach (var action in actions)
                    {
                        if (!actionsModel.Actions.Any(x => x.AIDAction == action))
                        {
                            actionsModel.Actions.Add(new ActionsModel.Action(action));
                        }

                        var actionModel = actionsModel.Actions.First(x => x.AIDAction == action);
                        if (action.IsModified)
                        {
                            var actionText = action.Text;

                            actionModel.OriginText = action.Text;

                            if (actionModel.AIDAction.Action.type == "continue")
                            {
                                if (AIDAdventuresContainer.StartsWithNewLine(actionText))
                                {
                                    actionText = actionText.Remove(0, 1);
                                }
                            }
                            else
                            {
                                if (AIDAdventuresContainer.EndsWithNewLine(actionText))
                                {
                                    actionText = actionText.Remove(actionText.Length - 1, 1);
                                }
                            }

                            actionModel.OriginText = actionText;

                            if (actionModel.TranslateWork != null)
                            {
                                actionModel.TranslateWork.Abort();
                                actionModel.TranslateWork = null;
                            }

                            actionModel.OnTranslating  = true;
                            var oldTranslatedText      = actionModel.TranslatedText;
                            actionModel.TranslatedText = oldTranslatedText + System.Environment.NewLine + "[번역중...]";
                            actionModel.TranslateWork  = actionTranslator.Translate(actionModel.OriginText, "en", model.TranslateLanguage,
                                                                                    (translated) =>
                            {
                                Dispatcher.Invoke(() =>
                                {
                                    var prevScrollableHeight   = actionsScrollViewer.ScrollableHeight;
                                    actionModel.TranslatedText = translated;
                                    this.actionsScrollViewer.UpdateLayout();

                                    var newScrollOffset = actionsScrollViewer.VerticalOffset - (prevScrollableHeight - actionsScrollViewer.ScrollableHeight);
                                    //DoSmoothScroll(this.actionsScrollViewer, newScrollOffset, new TimeSpan(0, 0, 1));
                                    this.actionsScrollViewer.ScrollToVerticalOffset(newScrollOffset);
                                });
                            }, failed: (reason) =>
                            {
                                Dispatcher.Invoke(() => { actionModel.TranslatedText = oldTranslatedText + System.Environment.NewLine + "[번역 실패] " + reason; });
                            }, finished: () =>
                            {
                                Dispatcher.Invoke(() => { actionModel.OnTranslating = false; });
                            });

                            action.IsModified = false;
                        }
                    }
                    actionsModel.Sort();

                    foreach (var head in actionsModel.Actions.ToArray())
                    {
                        if (!actions.Contains(head.AIDAction))
                        {
                            if (head.TranslateWork != null)
                            {
                                head.TranslateWork.Abort();
                                head.TranslateWork = null;
                            }
                            actionsModel.Actions.Remove(head);
                        }
                    }
                }
                UpdateDisplayAction();
            });
        }