/// <summary>
        /// Performs template save routine by specified path
        /// </summary>
        /// <param name="path">Path to save template</param>
        private void SaveTemplateByPath(string path)
        {
            if (this.SelectedTab is TemplateViewModel)
            {
                TemplateViewModel template = this.SelectedTab as TemplateViewModel;
                template.TemplateName = Path.GetFileNameWithoutExtension(path);

                // save .omr template data
                string jsonRes = TemplateSerializer.TemplateToJson(template);
                File.WriteAllText(path, jsonRes);

                path = path.Replace(".omr", template.ImageFileFormat);

                // save template image
                // if by some reason copy wasn't successful, manually save template image as png
                if (!string.IsNullOrEmpty(template.TempImagePath))
                {
                    if (!ImageProcessor.CopyUserTemplateImage(template.TempImagePath, path))
                    {
                        path = path.Replace(template.ImageFileFormat, ".png");
                        ImageProcessor.SaveTemplateImage(template.TemplateImage, path);
                    }
                }
                else
                {
                    path = path.Replace(template.ImageFileFormat, ".png");
                    ImageProcessor.SaveTemplateImage(template.TemplateImage, path);
                }

                template.IsDirty    = false;
                template.LoadedPath = path;
            }
        }
        /// <summary>
        /// Runs template finalization
        /// </summary>
        private void OnFinilizeTemplate()
        {
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += (sender, args) =>
            {
                string templateData   = TemplateSerializer.TemplateToJson(this, false);
                string additionalPars = string.Empty;

                try
                {
                    string           templateName       = Path.GetFileNameWithoutExtension(this.TemplateImageName) + "_template.omr";
                    FinalizationData finalizationResult = CoreApi.FinalizeTemplate(templateName, Encoding.UTF8.GetBytes(templateData), this.TemplateId, additionalPars);

                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        this.ProcessFinalizationResponse(finalizationResult);
                    });
                }
                catch (Exception e)
                {
                    DialogManager.ShowErrorDialog(e.Message);
                }
            };

            worker.RunWorkerCompleted += (sender, args) =>
            {
                BusyIndicatorManager.Disable();
            };

            BusyIndicatorManager.Enable();

            worker.RunWorkerAsync();
        }
        /// <summary>
        /// Runs template correction
        /// </summary>
        private void OnCorrectTemplate()
        {
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += (sender, args) =>
            {
                string templateData = TemplateSerializer.TemplateToJson(this, false);

                byte[] imageData = TemplateSerializer.CompressImage(this.TemplateImage, this.ImageSizeInBytes);

                //string imageData = TemplateConverter.CheckAndCompressImage(this.TemplateImage, this.ImageFileFormat, this.ImageSizeInBytes);

                string additionalPars = string.Empty;

                try
                {
                    TemplateViewModel correctedTemplate = CoreApi.CorrectTemplate(this.TemplateImageName,
                                                                                  imageData,
                                                                                  templateData,
                                                                                  this.WasUploaded,
                                                                                  additionalPars);

                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        this.ClearSelection();
                        this.PageQuestions.Clear();

                        this.AddQuestions(correctedTemplate.PageQuestions);
                        this.TemplateId = correctedTemplate.TemplateId;

                        this.FinalizationComplete = false;

                        double koeff     = this.TemplateImage.PixelWidth / correctedTemplate.PageWidth;
                        ZoomKoefficient *= koeff;
                        this.OnPropertyChanged(nameof(this.PageScale));

                        this.PageWidth   = correctedTemplate.PageWidth;
                        this.PageHeight  = correctedTemplate.PageHeight;
                        this.WasUploaded = true;

                        this.Warnings.Add("Template correction complete!");
                    });
                }
                catch (Exception e)
                {
                    DialogManager.ShowErrorDialog(e.Message);
                }
            };

            worker.RunWorkerCompleted += (sender, args) =>
            {
                BusyIndicatorManager.Disable();
            };

            BusyIndicatorManager.Enable();

            worker.RunWorkerAsync();
        }
        /// <summary>
        /// Saves template
        /// </summary>
        private void OnSaveTemplate()
        {
            string savePath = DialogManager.ShowSaveTemplateDialog();

            if (savePath == null)
            {
                return;
            }

            string jsonRes = TemplateSerializer.TemplateToJson(this, true);

            File.WriteAllText(savePath, jsonRes);
        }