using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.CompilerServices;

using Microsoft.Win32;
using static GetADoc.WinAPI;
using static System.ComponentModel.INotifyPropertyChanged;
using MSAPI = Microsoft.WindowsAPICodePack;
using System.ComponentModel;
using System.Windows.Controls.Primitives;
using System.Reflection.Emit;

namespace GetADoc
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;

            //デフォルトに前回の設定を表示
            ScreenCheckbox.IsChecked = Properties.Settings.Default.checkbox1Setting;
            IconCheckbox.IsChecked = Properties.Settings.Default.checkbox2Setting;
            SepaDocCheckbox.IsChecked = Properties.Settings.Default.checkbox3Setting;
            FreePageCheckbox.IsChecked = Properties.Settings.Default.checkboxFree;
            //RightClickCheckbox.IsChecked = Properties.Settings.Default.checkboxRight;
            //if ((bool)RightClickCheckbox.IsChecked)
            //{
            //    //RightClickCheckbox.Visibility = Visibility.Collapsed; //チェックボックスがONになっていれば非表示（過去に右クリック登録済み）
            //}
            ToggleButton.IsOn = Properties.Settings.Default.languageSetting;
            FolderDatePicker.SelectedDate = DateTime.Today;
            DateFolderNameBox.Text = "";
            SetDateFolderOptionState();

            //Pathの初期設定（引数指定で起動していれば引数のpath、指定していなければ前回の値）
            string[] argPathBox = Environment.GetCommandLineArgs();
            if (argPathBox.Length == 2)
            {
                FolderPathBox.Text = argPathBox[1];//第一引数を入力
                FolderPathBox.ScrollToHorizontalOffset(FolderPathBox.ExtentWidth);
            }
            else
            {
                FolderPathBox.Text = Properties.Settings.Default.box1Setting;//前回の値を入力
                FolderPathBox.ScrollToHorizontalOffset(FolderPathBox.ExtentWidth);
            }

            //Pathのテキストボックスを右端にスクロール
            FolderPathBox.ScrollToHorizontalOffset(FolderPathBox.ExtentWidth);

            //保存PathはデフォルトOFF
            //MyPathCheckbox.IsChecked = false;  //2024/12/27 保存Path廃止

            //文書スタイルのコンボボックス定義  
            string NormalItem = "";
            string QnAItem = "";
            //string ForErrorItem = "";
            string DesignItem = "";
            string MeetingMemoItem = "";
            string NativeItem = "Native";
            if (ToggleButton.IsOn)
            {
                NormalItem = "Normal";
                QnAItem = "QnA";
                //ForErrorItem = "Troubleshooting";
                DesignItem = "Basic Design";
                MeetingMemoItem = "Record of proceedings";
            }
            else
            {
                NormalItem = "ノーマル";
                QnAItem = "QnA";
                //ForErrorItem = "不具合解析";
                DesignItem = "基本設計資料";
                MeetingMemoItem = "議事録";
            }
            DocStileBox.Items.Add(NormalItem);
            DocStileBox.Items.Add(QnAItem);
            //DocStileBox.Items.Add(ForErrorItem);
            DocStileBox.Items.Add(DesignItem);
            DocStileBox.Items.Add(MeetingMemoItem);
            DocStileBox.Items.Add(NativeItem);
            //前回値を初期値に設定
            DocStileBox.SelectedItem = DocStileBox.Items[Properties.Settings.Default.formatSetting];

            //TitleLabelContent = "AsciiDocの雛形を作成します";
            //Label1Content = "作成先のフォルダ:";

            //ドラッグ&ドロップイベントの追加
            allBox.AddHandler(TextBox.DragOverEvent, new DragEventHandler(textBox_PreviewDragOver), true);
            allBox.AddHandler(TextBox.DropEvent, new DragEventHandler(textBox_Drop), true);
            FolderPathBox.AddHandler(TextBox.DragOverEvent, new DragEventHandler(textBox_PreviewDragOver), true);
            FolderPathBox.AddHandler(TextBox.DropEvent, new DragEventHandler(textBox_Drop), true);
        }

        //ファイル名指定のテキストボックスにフォーカスする（起動時:xamlヘッダで定義,<Loaded="Window_Loaded">）
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            FolderPathBox.ScrollToHorizontalOffset(FolderPathBox.ExtentWidth);//フォルダPathで浅い階層が見えるように
            ADocNameBox.Focus();
        }

        private void DateFolderOptionChanged(object sender, RoutedEventArgs e)
        {
            DeleteCompLabel(sender, e);
            SetDateFolderOptionState();
        }

        private void SetDateFolderOptionState()
        {
            bool isEnabled = DateFolderCheckbox.IsChecked == true;
            if (FolderDatePicker != null)
            {
                FolderDatePicker.IsEnabled = isEnabled;
            }
            if (DateFolderNameBox != null)
            {
                DateFolderNameBox.IsEnabled = isEnabled;
            }

        }

        private string GetOutputFolderPath(string baseFolderPath)
        {
            if (DateFolderCheckbox.IsChecked != true)
            {
                return baseFolderPath + @"\";
            }

            if (!FolderDatePicker.SelectedDate.HasValue)
            {
                string errMsg = "日付を指定してください";
                if (ToggleButton.IsOn)
                {
                    errMsg = "Please select a date.";
                }
                CustomMsgBox.Show(mainWindow, errMsg, "Date", MessageBoxButton.OK, MessageBoxImage.Warning);
                return null;
            }

            string folderName = DateFolderNameBox.Text == null ? string.Empty : DateFolderNameBox.Text.Trim();
            char[] invalidFolderChars = System.IO.Path.GetInvalidFileNameChars();
            if (folderName.IndexOfAny(invalidFolderChars) >= 0)
            {
                folderName = new string(folderName.Where(c => invalidFolderChars.Contains(c) == false).ToArray());

                string errMsg = "フォルダ名に使用できない文字が存在したため\n一部フォルダ名を修正しました。\nもう一度作成ボタンをクリックしてください。";
                if (ToggleButton.IsOn)
                {
                    errMsg = "Some folder names have been modified because they contained invalid characters. Please click the Create button again.";
                }

                CustomMsgBox.Show(mainWindow, errMsg, "Renamed this folder", MessageBoxButton.OK, MessageBoxImage.Warning);
                DateFolderNameBox.Text = folderName;
                return null;
            }

            string dateFolderName = FolderDatePicker.SelectedDate.Value.ToString("yyyyMMdd");
            if (folderName != string.Empty)
            {
                dateFolderName += "_" + folderName;
            }

            return System.IO.Path.Combine(baseFolderPath, dateFolderName) + @"\";
        }

        private string GetSequentialFileName(string filePath, string fileName)
        {
            string sequentialFileName = fileName;
            int index = 1;

            while (File.Exists(System.IO.Path.Combine(filePath, sequentialFileName + ".adoc")))
            {
                sequentialFileName = fileName + "_" + index;
                index++;
            }

            return sequentialFileName;
        }

        //保存Pathのチェックボックスをクリックする（ONにする）と登録したPahtをTextBoxに表示　  //2024/12/27 保存Path廃止
        //private void MyPathClick(object sender, RoutedEventArgs e)
        //{
        //    //ONにしたとき
        //    if(MyPathCheckbox.IsChecked == true)
        //    {
        //        FolderPathBox.Text = Properties.Settings.Default.savePathSetting;

        //        if (FolderPathBox.Text == "")
        //        {
        //            SavePathLabel.Visibility = Visibility.Visible;
        //        }
        //    }

        //    //OFFにしたとき
        //    if (MyPathCheckbox.IsChecked == false)
        //    {
        //        SavePathLabel.Visibility = Visibility.Hidden;
        //        FolderPathBox.Text = Properties.Settings.Default.box1Setting;
        //    }

        //}

        //フォルダ指定のためにファイルをドラッグ
        private void textBox_PreviewDragOver(object sender, System.Windows.DragEventArgs e)
        {
            if (e.Data.GetDataPresent(System.Windows.DataFormats.FileDrop, true))
            {
                e.Effects = System.Windows.DragDropEffects.Copy;
            }
            else
            {
                e.Effects = System.Windows.DragDropEffects.None;
            }
            e.Handled = true;
        }

        //エクスプローラーからテキストボックスにドロップして指定フォルダの場所をペースト
        private void textBox_Drop(object sender, System.Windows.DragEventArgs e)
        {
            var dropFiles = e.Data.GetData(System.Windows.DataFormats.FileDrop) as string[];
            if (dropFiles == null) return;

            //ドロップしたものがファイルの場合、1つ上の階層のフォルダを指す
            if (File.Exists(dropFiles[0]))
            {
                dropFiles[0] = dropFiles[0].Substring(0, dropFiles[0].LastIndexOf(@"\"));
            }

            FolderPathBox.Text = dropFiles[0];
            FolderPathBox.Focus();
            FolderPathBox.Select(this.FolderPathBox.Text.Length, 0);
        }

        //参照ボタンClickでフォルダ選択のダイアログを表示
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            var selectFile = new MSAPI::Dialogs.CommonOpenFileDialog();
            selectFile.IsFolderPicker = true;
            selectFile.Title = "Please Select Folder";
            selectFile.InitialDirectory = @"C:";
            if (selectFile.ShowDialog() != MSAPI::Dialogs.CommonFileDialogResult.Ok)
            {
                return;
            }
            FolderPathBox.Text = selectFile.FileName;
        }

        //作成ボタンClickでチェックボックスで要求された仕様のADocファイル一式を指定先フォルダに生成
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            
            bool IconFlag = false;
            bool SCREENFlag = false;
            bool SepaFlag = false;
            bool FreeFlag = false;
            if (IconCheckbox.IsChecked == true)//Iconsチェックボックスがオンのとき
            {
                IconFlag = true;
            }
            if (ScreenCheckbox.IsChecked == true)//SCREEN Logoチェックボックスがオンのとき
            {
                SCREENFlag = true;
            }
            if (SepaDocCheckbox.IsChecked == true)//分割ドキュチェックボックスがオンのとき
            {
                SepaFlag = true;
            }
            if (FreePageCheckbox.IsChecked == true)//freepageドキュチェックボックスがオンのとき
            {
                FreeFlag = true;
            }
            //drawio
            bool drawioFlag = false;
            if (Drawiobox.IsChecked == true)
            {
                drawioFlag = true;
            }

            //言語
            bool languageFlag = false;
            if (ToggleButton.IsOn)
            {
                languageFlag = true;
            }
            else
            {
                languageFlag = false;
            }


            //右クリック登録
            //string InstTxt = RightClickInst.RunInst();

            //RightClickCheckbox.IsChecked = true;
            //RightClickCheckbox.Visibility = Visibility.Hidden;
            //if (InstTxt != "")
            //{
            //    RightClickCheckbox.IsChecked = false;
            //    RightClickCheckbox.Visibility = Visibility.Visible;
            //    CustomMsgBox.Show(mainWindow, "Right click shortcut installation failed. Error: " + InstTxt, "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
            //}


            //ファイルパスが指定されていない or 指定したフォルダが存在しない場合
            if (FolderPathBox.Text == "" || !Directory.Exists(FolderPathBox.Text))
            {
                CustomMsgBox.Show(mainWindow, "保存先が存在しません", "The specified folder does not exist.", MessageBoxButton.OK, MessageBoxImage.Warning);
                Properties.Settings.Default.box1Setting = "";   //記憶していたパスを初期化
                Properties.Settings.Default.Save();
                return;
            }

            // テキストボックス2からfile名を取得
            var fileName = ADocNameBox.Text;
            if (ADocNameBox.Text == "")
            {
                fileName = "t";
            }
            //テキストボック1から保存場所を取得
            var filePath = GetOutputFolderPath(FolderPathBox.Text);
            if (filePath == null)
            {
                return;
            }

            // ファイル名に使用不可の文字が含まれている場合の処理
            char[] NgChars = System.IO.Path.GetInvalidFileNameChars();
            char[] cutComma = { '.' };
            if (fileName.IndexOfAny(NgChars) >= 0 || fileName.IndexOfAny(cutComma) >= 0)
            {
                fileName = RunBatch.NameCalibration(fileName);

                string ErrNameString = "ファイル名に使用できない文字が存在したため\n一部ファイル名を修正しました。" + "\"\\nもう一度作成ボタンをクリックしてください。";
                if (ToggleButton.IsOn)
                {
                    ErrNameString = "Some file names have been modified because they contained invalid characters. Please click the Create button again.";
                }

                    CustomMsgBox.Show(mainWindow, ErrNameString, "Renamed this file", MessageBoxButton.OK, MessageBoxImage.Warning);
                ADocNameBox.Text = fileName;
                return;
            }

            if (!Directory.Exists(filePath))
            {
                Directory.CreateDirectory(filePath);
            }

            fileName = GetSequentialFileName(filePath, fileName);
            ADocNameBox.Text = fileName;

            //指定したフォルダに同名の.adocや既存の付属ファイル(config.adocなど)がある場合の処理
            if (File.Exists(System.IO.Path.Combine(filePath, "config.adoc"))
                || Directory.Exists(System.IO.Path.Combine(filePath, "Images")) || Directory.Exists(System.IO.Path.Combine(filePath, "icons"))
                || Directory.Exists(System.IO.Path.Combine(filePath, "Sub_First")) || Directory.Exists(System.IO.Path.Combine(filePath, "Sub_Second")))
            {
                string SameNameMsg = "これから生成するファイルと同名のファイルが既に存在します" +
                    "\n既存のファイルを上書きしますか？" + "\n(Imageフォルダ内のファイルは維持されます)";
                string SameNameHadder = "指定したフォルダに既存のファイルが存在します";

                if (ToggleButton.IsOn)
                {
                    SameNameMsg = "A file with the same name as the file you are about to generate already exists. " +
                        "Do you want to overwrite the existing file? (The file in the Image folder will be maintained.)";
                    SameNameHadder = "The same name already exists.";
                }

                MessageBoxResult OverwriteADoc = CustomMsgBox.Show(mainWindow, SameNameMsg,
                SameNameHadder,
                MessageBoxButton.YesNo, MessageBoxImage.None);
                if (OverwriteADoc == MessageBoxResult.Yes)
                {

                }
                else if (OverwriteADoc == MessageBoxResult.No)
                {
                    CustomMsgBox.Show(mainWindow, "別のフォルダを指定してください", "Please select another directory",
                        MessageBoxButton.OK, MessageBoxImage.None);
                    return;
                }
            }

            //コンボボックスで選んでいるテンプレートの種類を読み込み
            string selectedTmpText = DocStileBox.Text;

            //バッチファイルの実行
            RunBatch.runBatch(IconFlag, SCREENFlag, SepaFlag, FreeFlag, languageFlag, drawioFlag, fileName, filePath, selectedTmpText);

            //保存Pathのラベルが表示されていれば、表示を隠す
            if (SavePathLabel.Visibility == Visibility.Visible)
            {
                SavePathLabel.Visibility = Visibility.Hidden;
            }
            //処理の完了を知らせるラベルを表示
            CompletedLabel.Visibility = Visibility.Visible;

            //指定されたファイルパスとチェックボックス、コンボボックスを保存
            Properties.Settings.Default.box1Setting = FolderPathBox.Text;
            Properties.Settings.Default.checkbox1Setting = ((bool)ScreenCheckbox.IsChecked);
            Properties.Settings.Default.checkbox2Setting = ((bool)IconCheckbox.IsChecked);
            Properties.Settings.Default.checkbox3Setting = ((bool)SepaDocCheckbox.IsChecked);
            //Properties.Settings.Default.checkboxRight = ((bool)RightClickCheckbox.IsChecked);
            Properties.Settings.Default.checkboxFree= ((bool)FreePageCheckbox.IsChecked);
            Properties.Settings.Default.formatSetting = ((int)DocStileBox.SelectedIndex);
            Properties.Settings.Default.languageSetting = ((bool)ToggleButton.IsOn);

            //保存PahtがTrueなら、そのときTextBoxに記載されているPathを保存
            //if (MyPathCheckbox.IsChecked == true)   //2024/12/27 保存Path廃止
            //{
            //    Properties.Settings.Default.savePathSetting = FolderPathBox.Text;
            //    SavedLabel.Visibility = Visibility.Visible;
            //}


            Properties.Settings.Default.Save();
        }

        //Helpボタンクリック処理（Helpページをブラウザで開く）
        private void helpButton_Click(object sender, RoutedEventArgs e)
        {
            //コンソール呼び出し
            ProcessStartInfo processStartInfo = new ProcessStartInfo();
            string appPath = System.Reflection.Assembly.GetExecutingAssembly().Location;  //モジュールのパスを取得
            string appDirectory = appPath.Substring(0, appPath.LastIndexOf(@"\") + 1);    //モジュールの存在するディレクトリを取得
            processStartInfo.FileName = System.IO.Path.Combine(appDirectory, "getADoc.Data", "getADoc.bat");
            processStartInfo.CreateNoWindow = true; // コマンドプロンプトを非表示
            processStartInfo.UseShellExecute = false; // シェル機能オフ

            //チェックボックスの状況に応じて引数を指定
            processStartInfo.Arguments = "/OpenAdocHelp";

            //GetADoc.batを実行
            Process process = Process.Start(processStartInfo);
            process.WaitForExit();
            process.Close();
        }

        private void RightInstRun(object sender, RoutedEventArgs e)
        {
            // カレントディレクトリを取得
            string currentDirectory = Environment.CurrentDirectory;
            currentDirectory += "\\.backup_registory\\InstAdocUI.js.bat.reg.txt";
            if (File.Exists(currentDirectory))
            {
                string ErrMsg = "右クリックのショートカットは既に登録されているか、一度インストールした際の生成物が残留しています。マニュアルを確認してクリーンナップしてください。";
                if (ToggleButton.IsOn)
                {
                    ErrMsg = "Right-click shortcuts are already registered or there is residual data from a previous installation. Check the manual and clean it up.";
                }
                CustomMsgBox.Show(mainWindow, ErrMsg, "The associated file already exists",
                        MessageBoxButton.OK, MessageBoxImage.None);
                return;
            }

            string InstTxt = RightClickInst.RunInst();

            string OKMsg = "処理は正常終了しました。エクスプローラを開き、動作を確認して下さい";
            if (ToggleButton.IsOn)
            {
                OKMsg = "The process was successful. Please open Explorer and check the operation.";
            }
            CustomMsgBox.Show(mainWindow, OKMsg, "The process was successful.",
                        MessageBoxButton.OK, MessageBoxImage.None);

        }

        //コントロール（テキストボックスなど）がフォーカスされたら処理完了のラベルを非表示にする
        private void DeleteCompLabel(object sender, RoutedEventArgs e)
        {
            CompletedLabel.Visibility = Visibility.Hidden;
            SavedLabel.Visibility = Visibility.Hidden;
        }

        private void LanguageChange(object sender, RoutedEventArgs e)
        {
            DataContext = this;
            if (ToggleButton.IsOn)
            {

                //表記を日本語に切替
                TitleLabel.Content = "AsciiDocの雛形を作成します";

                label1.Content = "作成先のフォルダ:";
                label2.Content = "ドキュメント名:";
                label4.Content = "オプション:";
                label5.Content = "文書フォーマット:";
                DateFolderCheckbox.Content = "日付フォルダ作成";
                //label7.Content = "日付:";
                //label8.Content = "フォルダ名:";

                CompletedLabel.Content = "作成が完了しました!";

                if (FolderPathBox.Text == "<select folder>" || FolderPathBox.Text == "")
                {
                    FolderPathBox.Text = "<フォルダ指定>";
                }

                button1.Content = "参照";
                button2.Content = "作成";
                RightClickInstButton.Content = "右クリックショートカット追加";
                HelpPageButton.Content = "ヘルプ";

                //ScreenCheckbox.Content = "SCREEN Logo";
                IconCheckbox.Content = "カスタムアイコン";
                SepaDocCheckbox.Content = "分割ドキュメント";
                FreePageCheckbox.Content = "フリーページ";
                Drawiobox.Content = "drawioファイル";
                //RightClickCheckbox.Content = "右クリックショートカット追加(初回のみ)";
                //MyPathCheckbox.Content = "保存Path";   //2024/12/27 保存Path廃止

                int SelectNum = DocStileBox.SelectedIndex;
                DocStileBox.Items.Clear();
                DocStileBox.Items.Add("ノーマル");
                DocStileBox.Items.Add("QnA");
                //DocStileBox.Items.Add("不具合解析");
                DocStileBox.Items.Add("基本設計資料");
                DocStileBox.Items.Add("議事録");
                DocStileBox.Items.Add("Native");
                DocStileBox.SelectedItem = DocStileBox.Items[SelectNum];

            ToggleButton.IsOn = false;
            }
            else
            {
                TitleLabel.Content = "Create a Template for an AsciiDoc Document";

                label1.Content = "Output Folder";
                label2.Content = "File Name";
                label4.Content = "Oputions";
                label5.Content = "Format";
                DateFolderCheckbox.Content = "Create dated folder";
                //label7.Content = "Date:";
                //label8.Content = "Folder Name:";


                CompletedLabel.Content = "Completed!";


                if (FolderPathBox.Text == "<フォルダ指定>" || FolderPathBox.Text == "")
                {
                    FolderPathBox.Text = "<Select Folder>";
                }

                button1.Content = "Browse...";
                button2.Content = "Create";
                RightClickInstButton.Content = "Add Right-Click Shortcut";
                HelpPageButton.Content = "Help";

                //ScreenCheckbox.Content = "SCREEN Logo";
                IconCheckbox.Content = "Custom Icons";
                SepaDocCheckbox.Content = "Split Document";
                FreePageCheckbox.Content = "Free Page";
                Drawiobox.Content = "DrawIo File";
                //RightClickCheckbox.Content = "add shortcut to right-click menu in Explorer (Just once)";
                //MyPathCheckbox.Content = "saved path";   //2024/12/27 保存Path廃止

                int SelectNum = DocStileBox.SelectedIndex;
                DocStileBox.Items.Clear();
                DocStileBox.Items.Add("Normal");
                DocStileBox.Items.Add("QnA");
                //DocStileBox.Items.Add("Troubleshooting");
                DocStileBox.Items.Add("Basic Design");
                DocStileBox.Items.Add("Record of proceedings");
                DocStileBox.Items.Add("Native");
                DocStileBox.SelectedItem = DocStileBox.Items[SelectNum];

                ToggleButton.IsOn = true;
            }
        }


        //トグルボタンで言語切替  ※トグルボタンの引用先：https://feynman.hatenablog.com/entry/2019/04/09/080000
        private bool ts_Status;
        public bool Ts_Status
        {
            get { return ts_Status; }
            set
            {
                DataContext = this;
                SetProperty(ref ts_Status, value);
                if (!processError)
                {
                    Task.Run(() => Ts_Process(value));
                }
                else
                {
                    processError = false;
                }
            }
        }

        public async void Ts_Process(bool val)
        {
            if (val)
            {
                bool ret = await Task.Run(() => TsTaskOn());
                if (!ret)
                {
                    processError = true;
                    Ts_Status = false;
                }
            }
            else
            {
                bool ret = await Task.Run(() => TsTaskOff());
                if (!ret)
                {
                    processError = true;
                    Ts_Status = true;
                }
            }
        }


        public bool TsTaskOn()
        {
            //Thread.Sleep(500);
            bool ret = (true && !DummyFlag);

            if (ret) Process_Status = true;
            return ret;
        }

        public bool TsTaskOff()
        {
            //Thread.Sleep(500);
            bool ret = (true && !DummyFlag);

            if (ret) Process_Status = false;
            return ret;
        }

        private bool process_Status;
        public bool Process_Status
        {
            get { return process_Status; }
            set { SetProperty(ref process_Status, value); }
        }

        private bool processError = false;

        private bool dummyFlag = false;
        public bool DummyFlag
        {
            get { return dummyFlag; }
            set { SetProperty(ref dummyFlag, value); }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Equals(storage, value)) return false;

            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }



    }
}

