using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Reflection;
using LibraryCS;

namespace WindowsFormsApp1
{
    public partial class Form2 : Form
    {
        // Variable Declarations
        public double[,] PZT;        // Массив значений функции Z
        public double ShagY;         // Шаг изменения аргументов Y
        public double MaxX, MinX, MaxY, MinY, ShagX;
        public int NN, I, J;
        public string FileN, FileE, LineS;
        public StreamReader StRead;
        public StreamWriter StWrit;
        public double[] PXT, PYT;    // Массив аргументов X, Массив значений функции Y
        public DateTime BT, FT;      // Время начала и окончания процесса
        public TimeSpan ST;          // Длительность процесса
        private ThreadCallBack tcallRes;
        private int TH;

        // Включим потоковые объекты как локальные переменные
        private ThreadWithState tstat1, tstat2, tstat3;
        private Thread thred1, thred2, thred3;

        public ThreadWithState[] tstat = new ThreadWithState[0];
        // Объявление массива объектов tstat класса ThreadWithState
        public Thread[] thred = new Thread[0]; // Объявление массива объектов thred класса Thread

        public Form2()
        {
            InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Создание объекта aDll класса Assembly и загрузка сборки LibraryCS.dll
            Assembly aDll = Assembly.Load("LibraryCS");

            // Создание объекта tDll типа String класса Type
            Type tDll = aDll.GetType("LibraryCS.ClassDllCS");

            if (tDll == null)
            {
                MessageBox.Show("Не удалось найти тип 'LibraryCS.ClassDllCS' в сборке 'LibraryCS'.");
                return;
            }

            // Создание объекта oDll класса Object для получения ссылки на удаленные объекты
            Object oDll = Activator.CreateInstance(tDll);

            // Создание объекта mDll класса MethodInfo для выявления атрибутов метода DllCallCS класса ClassDllCS
            MethodInfo mDll = tDll.GetMethod("DllCallCS");

            if (mDll == null)
            {
                MessageBox.Show("Не удалось найти метод 'DllCallCS' в типе 'LibraryCS.ClassDllCS'.");
                return;
            }

            // Ensure we are calling the method with the correct parameters
            try
            {
                // Create an array of objects to pass as parameters
                Object[] nDll = new Object[6];

                // Getting values from the textboxes
                TH = Convert.ToInt32(textBox6.Text);
                MinX = Convert.ToDouble(textBox1.Text);
                MaxX = Convert.ToDouble(textBox2.Text);
                MinY = Convert.ToDouble(textBox4.Text);
                MaxY = Convert.ToDouble(textBox5.Text);
                NN = Convert.ToInt32(textBox3.Text);  // Assuming textBox3 is used for NN

                nDll[0] = NN;
                nDll[1] = TH;
                nDll[2] = MinX;
                nDll[3] = MaxX;
                nDll[4] = MinY;
                nDll[5] = MaxY;

                // Вызов метода DllCallCS и передача туда списка аргументов nDll
                mDll.Invoke(oDll, nDll);
            }
            catch (TargetParameterCountException ex)
            {
                MessageBox.Show("Ошибка: несоответствие числа параметров. " + ex.Message);
                return;
            }

            BT = DateTime.Now;

            ConfigureProgressBar(NN);

            InitializeArrays(NN, MinX, MaxX);

            CalculatePYT(NN);

            WritePXTToFile("C://A_1.txt", PXT, NN);

            progressBar1.Value = progressBar1.Maximum;
            progressBar1.Refresh();

            UpdateTimeLabels(BT, DateTime.Now);

            // Создание и запуск потоков
            tstat = new ThreadWithState[TH]; // Создание массива объектов tstat класса ThreadWithState
            thred = new Thread[TH]; // Создание массива объектов thred класса Thread

            // Цикл создания потоков
            for (I = 0; I < TH; I++)
            {
                tstat[I] = new ThreadWithState(NN, MinX, MaxX, MinY, MaxY, I + 1, new ThreadCallBack(tcallRes));
                thred[I] = new Thread(new ThreadStart(tstat[I].ThreadDoWork));
                thred[I].Start();
            }

            // Ожидание завершения потоков
            for (I = 0; I < TH; I++)
            {
                thred[I].Join();
            }

            // Вывод результата
            StartBackgroundThread();
        }

        private void ConfigureProgressBar(int nn)
        {
            progressBar1.Maximum = nn <= 100 ? 100 : nn;
            progressBar1.Step = nn <= 100 ? 1 : nn / 100;
            progressBar1.Minimum = 0;
            progressBar1.Value = 0;
        }

        private void InitializeArrays(int nn, double minX, double maxX)
        {
            PXT = new double[nn];
            PYT = new double[nn];
            ShagX = (maxX - minX) / (nn - 1);
            PXT[0] = minX;

            for (I = 1; I < nn; I++)
            {
                PXT[I] = PXT[I - 1] + ShagX;
                UpdateProgress();
            }
        }

        private void CalculatePYT(int nn)
        {
            for (I = 0; I < nn; I++)
            {
                PYT[I] = Math.Cos(Math.Pow(PXT[I], 3)) *
                         (4 * Math.Sin(PXT[I]) - Math.Sin(12 * PXT[I]) - 3 * Math.Sin(4 * PXT[I]));
                UpdateProgress();
            }
        }

        private void WritePXTToFile(string filePath, double[] pxt, int nn)
        {
            using (StWrit = new StreamWriter(filePath, false, Encoding.Default))
            {
                LineS = "PXT: ";
                for (I = 0; I < nn; I++)
                {
                    LineS += pxt[I].ToString() + (I < nn - 1 ? "; " : ";\n");
                }
                StWrit.WriteLine(LineS);
            }
        }

        private void UpdateTimeLabels(DateTime start, DateTime end)
        {
            FT = DateTime.Now;
            label10.Text = start.ToString("HH: mm:ss: fff");
            label11.Text = end.ToString("HH: mm:ss: fff");
            ST = end - start;
            label12.Text = $"{ ST.Hours:D2}:{ ST.Minutes:D2}:{ ST.Seconds:D2}:{ ST.Milliseconds:D3}";
        }

        private void StartBackgroundThread()
        {
            PZT = new double[NN, NN];
            var tstat = new ThreadWithState(NN, MinX, MaxX, MinY, MaxY, TH, new ThreadCallBack(tcallRes));
            var thred = new Thread(new ThreadStart(tstat.ThreadDoWork));
            thred.Start();
            thred.Join();
        }

        private void UpdateProgress()
        {
            if ((progressBar1.Value + progressBar1.Step) < progressBar1.Maximum)
            {
                progressBar1.Value += progressBar1.Step;
                progressBar1.Refresh();
                FT = DateTime.Now;
                ST = FT - BT;
                label11.Text = ST.ToString();
                label11.Refresh();
            }
        }

        public static void TcallRes(int cNN, int cTH, double[] cXT, double[] cYT, double[,] cZT)
        {
            DateTime BTcb = DateTime.Now; // Время начала процесса
            string FileNcb = "C://A_cb_" + cTH.ToString() + ".txt"; // Формирование имени файла данных
            using (var StWritcb = new StreamWriter(FileNcb, false, Encoding.Default)) // Объект потока вывода
            {
                // Запись логики и данных в файл
                // Оставлю как комментарии, так как Вы не предоставили реализацию
            }
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            textBox1.Text = "1";
            textBox2.Text = "5";
            textBox3.Text = "10";
            textBox4.Text = "1";
            textBox5.Text = "5";
            textBox6.Text = "4";
        }

        private void DoWork(int tNN, double[] tXT, double[] tYT, double[,] tZT)
        {
            // Цикл для вычисления функции
            for (int i = 0; i < tNN; i++)
            {
                for (int j = 0; j < tNN; j++)
                {
                    tZT[i, j] = 4 * Math.Sin(tXT[i]) * Math.Cos(Math.Pow(tXT[i], 3))
                                - Math.Sin(12 * tYT[j]) * Math.Cos(Math.Pow(tXT[i], 3))
                                - 3 * Math.Sin(4 * tYT[j]) * Math.Cos(Math.Pow(tXT[i], 3));

                    if (progressBar1 != null && (progressBar1.Value + progressBar1.Step) < progressBar1.Maximum)
                    {
                        Invoke(new Action(() =>
                        {
                            progressBar1.Value += progressBar1.Step;
                            progressBar1.Refresh();

                            FT = DateTime.Now;
                            ST = FT - BT;
                            label11.Text = ST.ToString();
                            label11.Refresh();
                        }));
                    }
                }
            }

            // Вывод результатов в файл
            FileN = "C://A_1.txt"; // Формирование имени файла данных

            using (StWrit = new StreamWriter(FileN, false, System.Text.Encoding.Default))
            {
                LineS = BT.Year.ToString() + "." +BT.Month.ToString() + "." +BT.Day.ToString() + ", " +
                        BT.Hour.ToString() + ":" +BT.Minute.ToString() + ":" +BT.Second.ToString() + ":" +BT.Millisecond.ToString();
                StWrit.WriteLine(LineS); // Вывод строки в поток вывода

                // Цикл вывода данных в файл
                LineS = "PXT: ";
                for (int i = 0; i < tNN; i++)
                {
                    LineS += tXT[i].ToString() + "; "; // Занесение значения аргумента Х в строку
                }
                StWrit.WriteLine(LineS + "\n");

                // Цикл вывода в файл значений функции
                for (int i = 0; i < tNN; i++)
                {
                    LineS = ""; // Инициализация строки
                    for (int j = 0; j < tNN; j++)
                    {
                        LineS += tZT[i, j].ToString() + "; "; // Занесение значения функции в строку
                    }
                    StWrit.WriteLine(LineS); // Вывод строки в поток вывода
                }
            }
        }
    }
}

 mDll.Invoke(oDll, nDll);