using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;


using System.Text.RegularExpressions;
using System.IO;
//using makedll;


namespace Linearis_programozas
{
    public partial class Form1 : Form
    {        
        string nev="nev";//beolvasott file neve
        string celfg="celfg";//célfügvény neve;
        string rhs_name="rhs-";//rhs neve
        string ranges_name = "rng-";//rhs neve
        string bounds_name = "bounds-";//rhs neve
        System.Collections.ArrayList valt = new System.Collections.ArrayList();
        System.Collections.ArrayList felt = new System.Collections.ArrayList();
        static String curDir = Directory.GetCurrentDirectory();
        static String cd = curDir + "\\input.txt";
        string openfilename="";
        int back = 0, skal = 0;
  

        public Form1()
        {
            InitializeComponent();
        }        
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            string temp = textBox1.Text;
            Regex rgxHasInvalidChars = new Regex("[^0-9]");

            if (rgxHasInvalidChars.IsMatch(temp))
            {
                string msg = "Please give positive integer!";
                errorProvider1.SetError(textBox1, msg);
            }
            else
            {
                if (temp.Length > 5 && temp.Length != 0)
                {
                    errorProvider1.SetError(textBox1, "Maximum number of iterations : 32767");
                }
                else errorProvider1.SetError(textBox1, "");
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            solve();            
        }

        private void button2_Click(object sender, EventArgs e)
        {
            megnyit();
        }

        private void beolvas(string filename)
        {
            StreamReader SR;
            string S, temp;
            string temp1 = "", temp2 = "", temp3 = "", temp4 = "", temp5 = "";
            int i = 0, allapot=0;
            System.Collections.ArrayList sor = new System.Collections.ArrayList(); //egy sor tokenizálva 

            SR = File.OpenText(filename);

            valt.Clear();  //a kinulázás a többszöri megnyitás miatt kell
            felt.Clear();  //a kinulázás a többszöri megnyitás miatt kell

            while ((S=SR.ReadLine())!= null)//S != null)
            {
                i = 0;
                sor.Clear();
                foreach (string token in Tokenize(S))
                {
                    i++;
                    temp = token.Trim();
                    if (temp != "")
                    {
                        sor.Add(temp);
                        //annak eldöntése, hogy hol járunk a sor első sztringje alapján
                        if (sor.Count == 1) {
                            if (temp.ToUpper() == "NAME") allapot = 0;
                            else if (temp.ToUpper() == "ROWS") allapot = 1; 
                            else if (temp.ToUpper() == "COLUMNS") allapot = 2;
                            else if (temp.ToUpper() == "RHS") allapot = 3;
                            else if (temp.ToUpper() == "RANGES") allapot = 4;
                            else if (temp.ToUpper() == "BOUNDS") allapot = 5;
                            else if (temp.ToUpper() == "ENDATA") allapot = 6;
                        } 
                    }
                }
                
                if (sor.Count == 1) continue; //ha csak egy string van a sorban akkor új típusok adataokho értünk                
                i = 1;                
                switch (allapot){
                    case 0:
                        foreach (string text in sor)
                        {
                            if (i++==2) nev = text;
                        }
                        break;
                    case 1:
                        string r_op="", r_nev="",r_temp;
                        foreach (string text in sor)
                        {
                            if (i == 1) r_op = text;
                            else if (i == 2) r_nev = text;
                            i++;
                        }
                        if (r_op.ToUpper() == "N") {
                            celfg = r_nev;  // ez lesz a célfügvény neve
                            break;
                        }
                        if (r_op.ToUpper() == "L") r_temp = "<=";
                        else if (r_op.ToUpper() == "E") r_temp = "=";
                        else r_temp = ">=";
                        felt.Add(new Feltetelek(r_nev,"","",r_temp,""));
                        break;
                    case 2:
                        Boolean van=false;
                        foreach (string text in sor)
                        {
                            if (i == 1) temp1 = text;
                            else if (i == 2) temp2 = text;
                            else if (i == 3) temp3 = text;
                            else if (i == 4) temp4 = text;
                            else if (i == 5) temp5 = text;
                            i++;
                        }
                        foreach (Valtozok valtoz in valt)
                        {
                            if (valtoz.Name == temp1) van = true;
                            
                            //célfügvény felvitele ha van
                            if (temp2 == celfg && valtoz.Name == temp1) valtoz.Celfg = temp3;
                            if (sor.Count > 3 && temp4 == celfg && valtoz.Name==temp1) valtoz.Celfg=temp5;
                        }
                        if (!van)
                        {
                            Valtozok tt;
                            valt.Add(tt=new Valtozok(temp1, "","", "", "")); // ha még nem szerepel a változok között akkor felvesszük

                            if (temp2 == celfg) tt.Celfg = temp3;  //azért kell ide is, mert ha a célfügvény érték megadása akkor van amikro először szerepel a változó neve akkor a foreach-ben még nem létezika  változó
                            if (sor.Count > 3 && temp4 == celfg) tt.Celfg = temp5;
                        }
                        foreach (Feltetelek feltetel in felt)
                        {
                            if (feltetel.Name == temp2)
                            {
                                feltetel.Valtozok += " ";
                                if (feltetel.Valtozok != "" && temp3[0] != '-') feltetel.Valtozok += "+";
                                feltetel.Valtozok += temp3+"*"+temp1;
                            }
                            if (sor.Count > 3 && feltetel.Name == temp4) 
                            {
                                feltetel.Valtozok += " ";
                                if (feltetel.Valtozok != "" && temp5[0] != '-') feltetel.Valtozok += "+";
                                feltetel.Valtozok += temp5 + "*" + temp1;
                                //feltetel.Valtozok += " ";
                            }
                        }
                        break;
                    case 3:
                        foreach (string text in sor)
                        {
                            if (i == 1) temp1 = text;
                            else if (i == 2) temp2 = text;
                            else if (i == 3) temp3 = text;
                            else if (i == 4) temp4 = text;
                            else if (i == 5) temp5 = text;
                            i++;
                        }
                        rhs_name=temp1;
                        foreach (Feltetelek feltetel in felt)
                        {
                            if (feltetel.Name == temp2) feltetel.Ertek = temp3;
                            if (sor.Count > 3 && feltetel.Name == temp4) feltetel.Ertek = temp5;
                        }

                        break;
                    case 4:
                        foreach (string text in sor)                        
                        {
                            if (i == 1) temp1 = text;
                            else if (i == 2) temp2 = text;
                            else if (i == 3) temp3 = text;
                            else if (i == 4) temp4 = text;
                            else if (i == 5) temp5 = text;
                            i++;
                        }
                        ranges_name=temp1;
                        foreach (Feltetelek feltetel in felt)
                        {
                            if (feltetel.Name == temp2) feltetel.Ertek_bal = temp3; 
                        }
                        break;
                    case 5:
                        foreach (string text in sor)
                        {
                            if (i == 1) temp1 = text;
                            else if (i == 2) temp2 = text;
                            else if (i == 3) temp3 = text;
                            else if (i == 4) temp4 = text;
                            else if (i == 5) temp5 = text;
                            i++;
                        }
                        bounds_name = temp2;
                        foreach (Valtozok valtoz in valt)
                        {
                            if (valtoz.Name == temp3 && temp1.ToUpper() == "UP") valtoz.UpperBound = temp4;
                            else if (valtoz.Name == temp3 && temp1.ToUpper() == "LO") valtoz.LowerBound = temp4;
                            else if (valtoz.Name == temp3 && temp1.ToUpper() == "FX") valtoz.Fix = temp4;
                        }
                        break;
                    default: break;
                }
            }
            SR.Close();
            
            dataGridView1.DataSource = this.valtozokBindingSource;
            this.dataGridView1.DataSource = valt;
            dataGridView1.Refresh();
            dataGridView2.DataSource = this.feltetelekBindingSource;
            this.dataGridView2.DataSource = felt;
            dataGridView2.Refresh();
        }

        private void kiir(string filename) {

            if (openfilename == "")
            {
                curDir = Directory.GetCurrentDirectory();
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Filter = "mps files (*.mps)|*.mps|All files (*.*)|*.*";
                sfd.ShowDialog();
                
                string s = sfd.FileName;
                openfilename = s;

                s = s.Insert(s.IndexOf(@"\"), @"\");
                s = s.Replace("\r", "").Replace("\n", "");
                s = s.Replace(@"\", @"/");
                s = s.ToLower();

                TextWriter twr = new StreamWriter(cd, false, System.Text.Encoding.Default);
                // write a line of text to the file
                twr.Write(s);

                // close the stream
                twr.Close(); 
            }
            
            
            //string temp= filename;
            TextWriter tw = new StreamWriter(openfilename, false, System.Text.Encoding.Default);
            String sor="";

            // név kiírás
            sor+="NAME          "+nev;
            tw.WriteLine(sor);

            // rows kiirása
            tw.WriteLine("ROWS");
            foreach (Feltetelek feltetel in felt)
            {
                sor = "";
                if (feltetel.Op == "<=") sor += " L  ";
                else if (feltetel.Op == "=") sor += " E  ";
                else if (feltetel.Op == ">=") sor += " G  ";
                sor += feltetel.Name;
                tw.WriteLine(sor);
            }
            tw.WriteLine(" N  "+celfg);

            //columns kiirása
            System.Collections.ArrayList sorok = new System.Collections.ArrayList();
            tw.WriteLine("COLUMNS");
            
            foreach (Valtozok valtoz in valt)               //célfügvények
            {
                sor = "    ";
                if (valtoz.Celfg != "")
                {
                    sorok.Add(new Col_sor(valtoz.Name, celfg, valtoz.Celfg, true));                 
                }
            }
            foreach (Feltetelek feltetel in felt)           //normál mátrix elemek
            {
                int i = 0;
                string temp, eleje = "", vege = "";
                foreach (string token in Tokenize(feltetel.Valtozok))
                {
                    temp = token.Trim();
                    if (temp != "")
                    {
                        i = temp.IndexOf("*");
                        eleje = temp.Substring(0, i);
                        vege = temp.Substring(i + 1);
                        if (eleje == "" || vege == "") continue;
                        if (eleje[0] == '+') eleje = eleje.Substring(1);
                        sorok.Add(new Col_sor(vege, feltetel.Name, eleje, false));            
                    }
                }
            }

            sorok.Sort(new SorComparer());                      // rendetés és filba írás            
            
            foreach (Col_sor aktsorok in sorok)
            {
                sor = "    ";
                sor += aktsorok.Valtozo;
                while (sor.Length != 14) sor += " ";
                sor += aktsorok.Megszoritas;
                while (sor.Length + aktsorok.Ertek.Length != 36) sor += " ";
                sor += aktsorok.Ertek;
                tw.WriteLine(sor);
            }
            //rhs kiirása
            tw.WriteLine("RHS");
            foreach (Feltetelek feltetel in felt)
            {
                if (feltetel.Ertek != "")
                {
                    sor = "    ";
                    sor += rhs_name;
                    while (sor.Length != 14) sor += " ";
                    sor += feltetel.Name;
                    while (sor.Length + feltetel.Ertek.Length != 36) sor += " ";
                    sor += feltetel.Ertek;
                    tw.WriteLine(sor);
                }
            }

            //ranges kiirása
            Boolean elso = true;
            foreach (Feltetelek feltetel in felt)
            {   
                if (feltetel.Ertek_bal != "") {
                    if (elso) { 
                        tw.WriteLine("RANGES");
                        elso = false;
                    }
                    sor = "    ";
                    sor += ranges_name;
                    while (sor.Length != 14) sor += " ";
                    sor += feltetel.Name;
                    while (sor.Length+feltetel.Ertek_bal.Length != 36) sor += " ";
                    sor += feltetel.Ertek_bal;
                    tw.WriteLine(sor);
                }
            }
            //bounds kiirása
            elso = true;
            foreach (Valtozok valtoz in valt)
            {
                if (valtoz.LowerBound!="" || valtoz.UpperBound!="" || valtoz.Fix!="")
                {
                    if (elso)
                    {
                        tw.WriteLine("BOUNDS");
                        elso = false;
                    }

                    Boolean fix_val = false;
                    if (valtoz.Fix != "")
                    {
                        sor = " FX ";
                        sor += bounds_name;
                        while (sor.Length != 14) sor += " ";
                        sor += valtoz.Name;
                        while (sor.Length + valtoz.Fix.Length != 36) sor += " ";
                        sor += valtoz.Fix;
                        tw.WriteLine(sor);
                        fix_val = true;
                    }
                    if (valtoz.LowerBound != "" && fix_val==false)
                    {
                        sor = " LO ";
                        sor += bounds_name;
                        while (sor.Length != 14) sor += " ";
                        sor += valtoz.Name;
                        while (sor.Length + valtoz.LowerBound.Length != 36) sor += " ";
                        sor += valtoz.LowerBound;
                        tw.WriteLine(sor);
                    }
                    if (valtoz.UpperBound != "" && fix_val == false)
                    {
                        sor = " UP ";
                        sor += bounds_name;
                        while (sor.Length != 14) sor += " ";
                        sor += valtoz.Name;
                        while (sor.Length + valtoz.UpperBound.Length != 36) sor += " ";
                        sor += valtoz.UpperBound;
                        tw.WriteLine(sor);
                    }
                }    
            }
            //endata
            tw.WriteLine("ENDATA");

            tw.Close();
            Directory.SetCurrentDirectory(curDir);
        }


        public static string[] Tokenize(string equation)
        {
            Regex RE = new Regex(@" ");
            return (RE.Split(equation));
        }

        private void button3_Click(object sender, EventArgs e)
        {
            kiir(openfilename);
            solve();        
        }

        private void button5_Click(object sender, EventArgs e)
        {
            del_variable();            
        }

        private void button7_Click(object sender, EventArgs e)
        {
            del_constratint();
        }
        private void button4_Click(object sender, EventArgs e)
        {
            add_variable();
        }
        private void button6_Click(object sender, EventArgs e)
        {
            add_constratint();
        }
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            megnyit();        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            kiir(openfilename);
        }
        private void addVariableToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            add_variable();
        }
        private void deleteVariableToolStripMenuItem_Click(object sender, EventArgs e)
        {
            del_variable();
        }
        private void addConstratintToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            add_constratint();
        }
        private void deleteConstratintToolStripMenuItem_Click(object sender, EventArgs e)
        {
            del_constratint();
        }
        private void solveToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            solve();
        }
        private void saveSolveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            kiir(openfilename);
            solve();
        }
        private void megnyit()
        {
            curDir = Directory.GetCurrentDirectory();
            OpenFileDialog odf = new OpenFileDialog();
            odf.Filter = "mps files (*.mps)|*.mps|All files (*.*)|*.*";
            odf.FilterIndex = 1;
            odf.ShowDialog();
            label4.Visible = false;
            button8.Visible = false;
            if (odf.FileName != "")
            {
                string s = odf.FileName;
                openfilename = s;
                beolvas(s);
                label5.Text = "Problem's name: " + nev;

                s = s.Insert(s.IndexOf(@"\"), @"\");
                s = s.Replace("\r", "").Replace("\n", "");
                s = s.Replace(@"\", @"/");
                s = s.ToLower();


                TextWriter tw = new StreamWriter(cd, false, System.Text.Encoding.Default);
                // write a line of text to the file
                tw.Write(s);

                // close the stream
                tw.Close();

                Directory.SetCurrentDirectory(curDir);
            }
        }      
        private void add_variable() {
            Form2 f2 = new Form2();
            f2.ShowDialog();
            if (f2.textBox1.Text != "" && f2.ok) valt.Add(new Valtozok(f2.textBox1.Text, f2.textBox2.Text, f2.textBox3.Text, f2.textBox4.Text, f2.textBox5.Text));
            f2.Close();

            dataGridView1.DataSource = this.valtozokBindingSource;
            this.dataGridView1.DataSource = valt;
            dataGridView1.Refresh();
        }
        private void del_variable()
        {
            if (this.dataGridView1.SelectedRows.Count > 0)
            {
                valt.RemoveAt(this.dataGridView1.SelectedRows[0].Index);
                dataGridView1.DataSource = this.valtozokBindingSource;
                this.dataGridView1.DataSource = valt;
                dataGridView1.Refresh();
            }
        }
        private void add_constratint()
        {
            Form3 f3 = new Form3();
            f3.ShowDialog();
            if (f3.textBox1.Text != "" && f3.ok) felt.Add(new Feltetelek(f3.textBox1.Text, f3.textBox2.Text, f3.textBox3.Text, f3.comboBox1.Text == "" ? "=" : f3.comboBox1.Text, f3.textBox4.Text));
            f3.Close();



            dataGridView2.DataSource = this.feltetelekBindingSource;
            this.dataGridView2.DataSource = felt;
            dataGridView2.Refresh();    
        }
        private void del_constratint()
        {
            if (this.dataGridView2.SelectedRows.Count > 0)
            {
                felt.RemoveAt(this.dataGridView2.SelectedRows[0].Index);
                dataGridView2.DataSource = this.feltetelekBindingSource;
                this.dataGridView2.DataSource = felt;
                dataGridView2.Refresh();
            }    
        }
        private void solve()
        {
            makedll.Szamol sz = new makedll.Szamol();
            Regex rgxHasInvalidChars = new Regex("[^0-9]");
            int i, max = 0, mod = 0, it = 10000, tol = 2, param = 0;
     

            DateTime start;
            DateTime end;
            TimeSpan ts;

            if (Maximum.Checked == true) max = 1;
            if (Dantzig.Checked == true) mod = 1;
            if (!rgxHasInvalidChars.IsMatch(textBox1.Text) && textBox1.Text.Length <= 5 && textBox1.Text.Length != 0) it = Convert.ToInt32(textBox1.Text);
            if (checkBox1.Checked) skal = 1;
            if (numericUpDown1.Value != 2) tol = (int)numericUpDown1.Value;

            //i = sz.doit2(max, mod, it);//,skal,tol);

            param += max;
            param += mod * 10;
            param += skal * 100;
            param += tol * 1000;

            //Form4 f4 = new Form4(it, param);
            //f4.ShowDialog();
            //f4.calldll(it, param, sender, e);

            //i = sz.doit2(it,param);
            //start = DateTime.Now;

 
            
            //MessageBox.Show("FUCK");
            label4.Text = "Please wait for result!";
            label4.ForeColor = System.Drawing.Color.Red;
            label4.Visible = true;
            button8.Visible = false;
            this.Update();
            
            i = sz.call_RetroLP(it, param);
  

           
            label4.Text = "Klick here to see result:";
            label4.ForeColor = System.Drawing.Color.Black;
            button8.Visible = true;
            this.Update();

            sz = null;
          

         
        }

       

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openfilename = "";
            celfg = "celfg";
            button8.Visible = false;
            label4.Visible = false;
            label5.Visible = false;
            valt.Clear();
            felt.Clear();
            dataGridView1.DataSource = this.valtozokBindingSource;
            this.dataGridView1.DataSource = valt;
            dataGridView1.Refresh();
            
            dataGridView2.DataSource = this.feltetelekBindingSource;
            this.dataGridView2.DataSource = felt;
            dataGridView2.Refresh();
        }

        private void button8_Click(object sender, EventArgs e)
        {
            Form4 f4 = new Form4(curDir,nev,skal);
            f4.ShowDialog();
        }

   
    }
}