#pragma warning disable 642

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Net.Mail;

using System.Globalization;
using Args;
using Logger;
using wnd;
///
/// \brief Пространство имен содержит  тест-юнит для тестирования библиотеки args.
/// 
///
namespace test
{

/// \file  Program.cs

/// \brief класс содержит глобальные переменные для ключей, тест юнит Main и функцию выдачи подсказки
   
/// Приложение демонстрирует использование библиотеки разбора 
/// командной строки. Использует систему журналирования LOGGER.
/// Есть ключи всех типов - логический (так же называется флагом), 
/// вещественный, целый и строчный.
/// Занимается тем, что записывает в журнал системы 
/// сообщения всех уровней важности, что задается параметром ключа -l.
/// Если ключу -p присвоить значение 0.5, то он будет установлен в 0.1.
/// Один из ключей -t1, -t2 и t3 является обязательным. Они передаются
/// в метод mkVHelp класса Arg во втором аргументе и не обрамляются квадратными скобками.
/// 

    class Program    {



        static public ArgFlg  hlpF ;  ///<[флаг](@ref Args.ArgFlg) подсказки.
        static public ArgFlg  dbgF ;  ///<флаг отладки
        static public ArgFlg  vF ;    ///<флаг для дублирования журналирования в стандартный вывод

        
///   \code
///         Пример обьявления целых, строчных плавающих и  логических переменных для ввода аргументов командной строки
///
        static public ArgIntMM    logLvl ;  ///< ключ целого типа
        static public ArgStr      logNm ;  ///<чтобы задать уровень журналирования именем (в данном приложении не используется).
        static public ArgFloatMM  perCent ;  ///<   ключ плавающего типа
        static public ArgStr  flNm ;         ///<  ключ типа строка
        static public ArgFlg  tsk1 ;         ///<  пример ключа для выбора работы1.
///   \endcode

        
        static public ArgFlg  tsk2 ;         ///<  пример ключа для выбора работы2,
        static public ArgFlg  tsk3 ;         ///<  пример ключа для покаать окно ввода, параметров
                                             ///< один из ключей обязан быть в командной строке.

         static  Program()       ///< статический конструктор для глобальных переменных
        {
           string lLvl = "log level names:{"+Loger.ILList()+"}";             

           logNm  =  new ArgStr  ("Error",    "ln",  "logName",   lLvl, "NNN");
           hlpF   =  new ArgFlg(false, "?","help",    "to see this help");
           vF     =  new ArgFlg(false, "v",  "verbose", "additional info");
           dbgF   =  new ArgFlg(false, "d",  "debug",   "debug mode");
           tsk1   =  new ArgFlg(false, "t1",  "workOne",   "to do some work");
           tsk1.show = false;
           tsk2   =  new ArgFlg(false, "t2",  "workNext",   "to do another work");
           tsk2.show = false;
         //  dbgF.required = true;
                                         
///   \code
///        Пример создания обьектов, задаются значение по умолчанию, короткое имя, синоним, подсказка и обозначене параметра
///        аргумента.   
         

           tsk3   =  new ArgFlg(false, "t3",  "window",   "to show dialog window");
           tsk3.show = false;    //  отменить автоматическое добавление   аргумента в ком.строку подсказки,
                                 //  аргумент добавляется к  подсказке во втором  параметре 
                                 //   Arg.mkVHelp

           logLvl =  new ArgIntMM(1,      "l",  "log",   "log level", "LLL");
           logLvl.setMin(1);      //  задаем минимальные и максимальные значеня аргумента
           logLvl.setMax(8);      //

           //logLvl.show = false;
           flNm   =  new ArgStr("somefile.dat", "f", "file", "data file", "FLNM");
           flNm.required = true;       // нет квадратных скобок
//           flNm.show = false;

           perCent   =  new ArgFloatMM(0.05, "p", "percent", "percent for something",  "PPP");
           perCent.setMax(100.0);
///   \endcode
        }

        static public void version (out int major, out int minor, out int build){
             System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly(); 
             System.Version ver = asm.GetName().Version;
             major =  ver.Major;
             minor =  ver.Minor;
             build =  ver.Build;
        }

/** 

 Показать строку подсказки и прекратить работу приложения.
 В командной строке оператор обязан задать один из ключей -t1 или -t2,
 поэтому у переменных  tsk1 и tsk2 задано свойство не показывать,
 а они появляются во втором параметре функции mkVHelp.



        
*/        
        
///   \code
///     Пример создания метода  usage
        
        static public  void usage(){

           Arg.mkVHelp("to test command line arguments" // подсказка по утилите
                        ,  "-t1 | -t2 | -t3"            // автоматическая вставка этих аргументов в ком. строку была отключена
                 , vF
                 , Arg.mkArgs(
                   hlpF
                  ,dbgF
                  ,vF
                  ,logNm
                  ,logLvl
                  ,perCent
                  ,flNm
                  ,tsk1
                  ,tsk2
                  ,tsk3
                 )
                );
                Environment.Exit(1);
        }

///   \endcode


/** 

  Работа тест юнита при введенных ключах '-v' и '-?' заключается
 в вызове данного метода `test.usage()`, который 
  в стандартный вывод ошибок выводит следующей текст 

-----

     to test command line arguments (ver:2.10.0)
     usage:
      a [-?] [-d] [-v] [-ln NNN] [-l LLL] [-p PPP] -f FLNM  -t1 | -t2 | -t3
     options:
       -?                : to see this help: True
       -d                : debug mode: False
       -v                : additional info: True
       -ln NNN       : log level names:{Spam Debug Warning Stats Error FatalError Info Ignore}: Error
       -l LLL        : log level (1..8): 1
       -p PPP        : percent for something (..100): 0.05
       -f FLNM       : data file: somefile.dat
       -t1               : to do some work: False
       -t2               : to do another work: False
       -t3               : to show dialog window: False
     '?' means the same as 'help'
     'd' means the same as 'debug'
     'v' means the same as 'verbose'
     'ln' means the same as 'logName'
     'l' means the same as 'log'
     'p' means the same as 'percent'
     'f' means the same as 'file'
     't1' means the same as 'workOne'
     't2' means the same as 'workNext'
     't3' means the same as 'window'


-----
        
*/

        [STAThread]
        static public void Main(string[] args)
        {


           for (int i = 0; i<args.Length; i++){
             if (hlpF.check(ref i, args))
               usage();
             else if (dbgF.check(ref i, args))
               ;
             else if (vF.check(ref i, args))
               ;
             else if (logNm.check(ref i, args))
               ;
             else if (logLvl.check(ref i, args))
               ;
             else if (perCent.check(ref i, args))
               ;
             else if (flNm.check(ref i, args))
               ;
             else if (tsk1.check(ref i, args))
               ;
             else if (tsk2.check(ref i, args))
               ;
             else if (tsk3.check(ref i, args))
               ;
           }
           if (!tsk1 && !tsk2 && !tsk3)
             usage();

           DateTime st = DateTime.Now;
           using (Loger Logger = new Loger(logNm, dbgF)){
                        if (vF)
                           Logger.cnslLvl = IMPORTANCELEVEL.Stats;

///   \code
///     Пример создания окна диалогового для ввода параметров 
        
              if (tsk3) {
                 ArgStr user = new ArgStr("NuFoo", "pwd", "user", "input your login here");
                 user.edit = false;           // запрет редактирования

                 ArgStr pwd = new ArgStr("default", "pwd", "password", "input your password here");
                 pwd.isPassword = true;       // забить звездочками вводимое значение

                 ArgStr email = new ArgStr("email@example.com", "email", "email", "email of user");
                 email.txtChanged = check;    // вызвать метод check для проверки правильности ввода
                 ArgStr test_Str_Arr = new ArgStr("Black", "c", "color", "color", "chose some color"
                   , WCNST.colors             // показать список возможных альтернатив
                 
                 );
                        

                 OkCancelDlg it = new OkCancelDlg( "window to input some params", Logger
                                    , user
                                    , pwd
                                    , email
                                    , perCent
                                    , test_Str_Arr );

                 DialogResult rc = it.ShowDialog();
                 if (rc == DialogResult.OK) {
                    Console.WriteLine ("your input : {0}/{1}/{2}/{3}/{4}"
                      ,  (string)user
                      ,  (string)pwd
                      ,  (string)email
                      ,  (string)test_Str_Arr
                      ,  (double) perCent
                      
                      );
                 }
                 else 
                    Console.WriteLine ("nothing to show");
              }

///   \endcode

              else {                                 
                for (uint i = 0; i < 9; i++)
                {
                    Logger.WriteLine(LOGGER.uitoLvl(i)
                        ,"this is {0} iteration {1}  "
                        , i, LOGGER.uitoLvl(i)
                    );
                    Thread.Sleep(500);
                }

                if (perCent == 0.5)  {
                  perCent.set(0.1);  
                  Logger.WriteLine( IMPORTANCELEVEL.Info
                      ,"...0.5 has been changed to 0.1..."
                      ,  (double)  perCent
                  );
                }
              }

              DateTime fn = DateTime.Now;
              Logger.WriteLine(IMPORTANCELEVEL.Stats, "time of work with file '{1}' is {0} secs"
                   , (fn - st).TotalSeconds, (string)flNm);

           }
        }

        /// \brief чтобы продемонстрировать проверку ввода
        public static bool check(object sender, string email)
        {
            try
            {
                MailAddress m = new MailAddress(email);
                return true;
            }
            catch
            {
                return false;
            }
        }

    }
    public class WCNST
    {
        public static string[] colors;
        static WCNST()
        {
            colors = new string[] { "DarkBlue", "Red", "Green", "Blue", "Yellow", "Cyan" };
        }

    }

                   
}
