//#pragma warning disable 219

//
#define PANEL
//#define DEBUG
//#define LAYOUT
using System;
using System.Data;
using System.Windows;
using System.Drawing;

using System.Windows.Forms;
//using System.Windows.Controls;
using System.Text.RegularExpressions;
using Args;
using Logger;
 
/// \brief пространство имен для  генерации диалоговых окон
 namespace wnd
{

           /// \brief родительский класс для диалоговых окон
        public abstract class BaseDialog : DialogModel {
        protected _TextBox t1;           ///< поле ввода 
        protected Label l1;              ///< метка для поля ввода
        protected ComboBox cb1;
        protected int txtNo;             ///< здесь записано кол-во полей ввода
        public bool dbg;
        protected System.Drawing.Size bSz2; ///<это размер поля ввода, в два раза шире стандартной кнопки.
        ///
        public Loger l;
        protected bool justShow = false;   ///< отмена редактирования

        protected abstract void DoStuff(); // Insert code before base
        public _Button OK_but;  

        protected System.Windows.Forms.TableLayoutPanel mainTable;
        protected Arg[] ps;
        protected int w,h;

        public BaseDialog(               ///< для наследования функции addFld в окно для ввода многих строчек
                 string name             ///<  имя окна ввода
                   , Loger ll = null     ///<  журнал для отладки окна
                       )
            : base(name, 2) {

            bSz2 = new System.Drawing.Size(wnd.SZ.X_BUTTON * 2, wnd.SZ.Y);   /// ширина для поля ввода
            Name = "InputText window";
            l = ll;
            txtNo = 0;
            if (l != null)
                l.WriteLine("{0} ctor  title '{1}'", Name, name);

            Load += loadH;
        }
                 
         public BaseDialog      ///этот конструктор для создания нескольких полей ввода
               (
                 string name          ///заголовок окна
                  , Loger ll
                 , params  Arg[] ps  ///список переменных для создания полей ввода
                       )
            : this(name, ll) {
            init(ps);
                
            DoStuff();
            this.ps = ps;
        }

        public BaseDialog(string name   ///< заголовок окна
                 , Arg p                ///< переменная для ввода
                    , Loger ll = null   ///< журнал для отладки

                         )
            : this(name, ll) {

                DoStuff();
        initTableLayout();  
            addFld2(1, p);
            setWidth();
        }
    
        void initTableLayout ()
        {
            mainTable = new TableLayoutPanel();
            mainTable.Dock = DockStyle.Top;
            mainTable.SuspendLayout();
            mainTable.AutoSize=true;
            
            mainTable.ColumnCount = 2*w-1;
            mainTable.RowCount = h;
            mainTable.Margin = new System.Windows.Forms.Padding(4);
            float cC= 1f/w*80;
            float cR= 1f/h*100;
            for(int i=0;i<mainTable.ColumnCount;i++)
            {
                if(i%2==0)
                mainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent,cC));
                else mainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent,1f/w*20));
                for(int j=0;j<h;j++)
                mainTable.RowStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent,cR));    
            
            }
            mainTable.ResumeLayout(false);
            mainTable.PerformLayout();
            
            this.Padding = new Padding(20, 20, 20, 20);         
            this.Controls.Add(mainTable);
            
        }
        
     
        void init(Arg[] ps) {
        if(ps.Length>20) 
        {
            w=3;
            if(ps.Length%w==0) h=ps.Length/w;
            else
                h=ps.Length/w+1;
            
        }
        else if(ps.Length>10)
        {
            w=2;
            if(ps.Length%w==0) h=ps.Length/w;
            else
                h=ps.Length/w+1;
        }
        else
        {
            h=ps.Length;
            w=1;
        }
        initTableLayout();                  
            this.AcceptButton = null;       /// в констукторе отменяется  нажатие клавиши Enter как на  кнопку Ok

 
            for (int i = ps.Length-1; i >=0; i--) 
            {
                addFld2(i, ps[i]);       ///
            }
            setWidth();
        }
            public void addFld2          /// метод добавляет в окно новое поле ввода
          (int n, Arg par) {

            Padding pd = new Padding(5, 0, 5,5);   ///
            Panel p = new Panel();               /// панель содержит метку и поле ввода
            p.Name = string.Format("p{0}", n);
                p.BorderStyle = BorderStyle.FixedSingle;
            if (dbg)
                p.BorderStyle = BorderStyle.FixedSingle;
            p.Size = new Size(1, bSz.Height + 1 * SZ.X_SPC);
            p.Dock = DockStyle.Top;
            //p.Padding = pd;    ///
            int col, row;
            col = n/h;
            row = (n%h); 
            col=col*2;
        
        if (par.vals == null) {
        //if (par.Equals(typeof(ArgFlg))) {
        if (par.GetType() == typeof(ArgFlg) && justShow) {
            addComboBox(n, par, p, new string[] {"True", "False"});
        }
        else {
                addBox(n, par, p);
        }
        } 
        else {
        addComboBox(n, par, p, par.vals);
        
        }
            addLabel(n, par, p);            
            
            mainTable.Controls.Add(p, col, row);
            txtNo++;
        }
       
    protected void addComboBox(int n, Arg par, Panel p, string[] values) {
        cb1 = new ComboBox();
//      cb1.TabIndex = n;
                cb1.Name = string.Format("p{0}", n); 
        cb1.Width = (int)(bSz2.Width/1.5);
                cb1.Dock = DockStyle.Right;
        cb1.Text = par.val();       
        
        foreach (string val in values) {
            cb1.Items.Add(val);
        }   
        
        p.Controls.Add(cb1);    
        
    }
    
        protected void addBox (int n, Arg par, Panel p) {
            t1 = new _TextBox(par);
//            t1.TabIndex = n;
            t1.Name = string.Format("p{0}", n); ;
            //t1.Size = bSz2;
            t1.Width = (int)(bSz2.Width/1.5);
            t1.Dock = DockStyle.Right;
            t1.restore();
////qq            t1.KeyDown += _KeyDown;

            t1.txtChanged = par.txtChanged;
            t1.TextChanged += new EventHandler(_TextChanged);
            if (par.isPassword) {
                t1.UseSystemPasswordChar = true;
            }

            if (!par.edit) {
                t1.ReadOnly = true;
            }

            p.Controls.Add(t1);

            
        }

        protected void addLabel(int n, Arg par, Control p) {
            l1 = new Label();
            ToolTip toolTip1 = new ToolTip();
            l1.Name = string.Format("l{0}", n);
           // l1.Size = bSz2;
            l1.Width = bSz2.Width / 2;
//            l1.Text = par.lNm;  /// создать новую строку
            l1.Text = Names.Text( par.lNm);  /// создать новую строку
            l1.Dock = DockStyle.Left; 
            toolTip1.SetToolTip(l1, par.longHelp());
        //l1.TextAlign = ContentAlignment.TopRight;
            if (dbg)
                l1.BackColor = Color.Blue;

            p.Controls.Add(l1);
        }

        public void loadH(object sender, System.EventArgs e) {
            if (l != null)
                l.WriteLine(
                     " '{0}': Load is here {1}", Name, (l == null) ? "null" : "not null");
                        

        }

        _TextBox getTextBox(int oNo) {
            _TextBox foo;
            Panel foo1;
            foreach (Control y in Controls) {
                if (y is Panel) {
                    foo1 = (Panel)y;
                    if (l != null)
                        l.WriteLine(
                                  "IT:Esc button pressed    text/save: first for '{0}'", foo1.Name);
                    foreach (Control x in foo1.Controls) {
                        if (x is _TextBox) {
                            foo = (_TextBox)x;
                            if (foo.ordNo() == oNo)
                                return foo;
                        }
                    }
                }
            }
            return null;
        }


        public void EnableTextBoxes(bool b, string name) {                         // NEW Блокирую OK_but и все поля ввода кроме поля с именем name 
            foreach (Control c in mainTable.Controls) {
                bool isTextBox = c is Panel && c.Name != name;
            foreach (Control c2 in c.Controls) {
                bool isTextBox2 = ((c2 is _TextBox) || (c2 is ComboBox))  && c2.Name != name;

                if (isTextBox2) {
                    c2.Enabled = b;
                }
                }
            }
        
            
        }
        void _TextChanged(Object sender, EventArgs e) {                     // NEW  Обработчик изминения текста поля ввода
            _TextBox current = (sender as _TextBox);
            string tb_name = current.Parent.Name;                     // NEW  Имя поля ввода
            string tb_text = current.Text.Trim();              // NEW  Текст поля ввода
            var inType = current.txtChanged;             // NEW  Тип поля ввода.
            bool enable =   inType(sender, tb_text);    

            this.EnableTextBoxes(enable, tb_name);
            OK_but.Enabled = enable;
        }

        public void setWidth() {
            this.Width = (bSz2.Width * 2 - 20)*w;
        }
    }
   

    public class DialogModel : System.Windows.Forms.Form {

        protected Size bSz;
    
        public DialogModel(
            string q = "question for OkCancel window" /// заголовок окна
          , int www = 1            /// минимальное количество дополнительных панелей между кнопками ок, канел
        ) {
            Padding _pd;
            Name = "OkCancel";
            Text = q;

            MinimizeBox = false;
            MaximizeBox = false;
            ControlBox = false;
            AutoScroll = false;
            FormBorderStyle = FormBorderStyle.FixedDialog;
            AutoSize = true;
            DialogResult = DialogResult.Cancel;

            bSz = countBaseSize();
            Size =  bSz;

            Panel p0 = new Panel();           // P0 эта панель задает высоту строки
            p0.Size = bSz;

            p0.Dock = DockStyle.Top;
            Controls.Add(p0);               //  первую панель положили вниз

            Panel p = new Panel();      // `p` дополнительная панель между кнопками ок, кансел

            SizeF sizef;                     //подстраиваем размер окна под заголовок
            Graphics g = CreateGraphics();
            StringFormat sf = new StringFormat(StringFormatFlags.DirectionRightToLeft);
            sizef = g.MeasureString(q, System.Drawing.SystemFonts.CaptionFont, Int32.MaxValue, sf);
            if (sizef.Width - bSz.Width * 2 > bSz.Width * www)
                p.Size = new Size((int)(sizef.Width) - bSz.Width * 2, bSz.Height);
            else
                p.Size = new Size(bSz.Width * www, bSz.Height);

            _pd = new Padding(SZ.X_SPC * p.Size.Width / 30 - 1, SZ.Y_SPC
                                , SZ.X_SPC * p.Size.Width / 30 - 1, SZ.Y_SPC);
                
            Padding = new Padding(0, 20, 0, 20);
              //                  , 10, SZ.Y_SPC);
            p.Dock = DockStyle.Right; ;
            Controls.Add(p);

            Location = new Point(wnd.SZ.X_SPC * 20, wnd.SZ.Y_SPC * 20);
            this.StartPosition = FormStartPosition.CenterParent;
        }

         protected Size countBaseSize () {
             return new Size(wnd.SZ.X_BUTTON, wnd.SZ.Y);
         }
    }
}