using System;
using System.Xml;
using System.IO;

namespace MyCompany.Server
{

    public class Service : MarshalByRefObject
    {
        private string c;
        private int[] w;
        private int[] q;                //Hodnota modula
        private int mAP;                //Předpočítáná hodnota pro Montgomeryho alg.
        private string t_r;
        private bool eraseTokenList;
        private int count;              //určuje číslo následujícího tokenu
        private int poradi;             //pořadí aktuálně ukládaného tokenu

        //Následujicí metody slouží pro přístup do privátních proměnných 'c, w, q, pocetTokenu, eraseTokenList'
        private void setC(string c)
        {
            this.c = c;
        }
        public string getC()
        {
            return this.c;
        }
        private void setW(int[] w)
        {
            this.w = w;
        }
        public int[] getW()
        {
            return this.w;
        }
        private void setQ(int[] q)
        {
            this.q = q;
        }
        public int[] getQ()
        {
            return this.q;
        }
        private void setMAP(int mAP)
        {
            this.mAP = mAP;
        }
        public int getMAP()
        {
            return this.mAP;
        }
        private void setT_r(string t_r)
        {
            this.t_r = t_r;
        }
        public string getT_r()
        {
            return this.t_r;
        }
        public void setEraseTokenList(bool eraseTokenList)
        {
            this.eraseTokenList = eraseTokenList;
        }
        private bool getEraseTokenList()
        {
            return this.eraseTokenList;
        }
        private void setCount(int count)
        {
            this.count = count;
        }
        public int getCount()
        {
            return this.count;
        }

        //----------------------------------------------------------------------------
        //Meotoda pro uloženi tokenu s podpisem na smartkartu do složky C:/Pub/TokenList.xml
        //----------------------------------------------------------------------------
        public void PutOnCard_token(string token_a, string sig_PA, string r)
        {
            //Jestli existuje soubor TokenList.xml a byl prijat priznak na smazani souboru
            if (eraseTokenList == true && File.Exists("C:/Data/TokenList.xml"))
            {
                //smaz soubor TokenList.xml
                File.Delete("C:/Data/TokenList.xml");
                this.poradi = 1;
            }
            setEraseTokenList(false);
            
            //Jestli neexistuje soubor TokenList.xml 
            if (!File.Exists("C:/Data/TokenList.xml"))
            {
                //vytvori soubor TokeList.xml v dane lokaci
                FileStream file = new FileStream("C:/Data/TokenList.xml", FileMode.OpenOrCreate, FileAccess.Write);                
                StreamWriter sw = new StreamWriter(file);

                //Do promenne 'token' se ulozi vsechny potrebne hodnoty. Text je formovan do vzheldu XML dokumentu.
                string token = "";
                token = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
                token += "<token id=\"1\">\n";
                token += "\t<a>" + token_a + "</a>\n";
                token += "\t<sigPA>" + sig_PA + "</sigPA>\n";
                token += "\t<r>" + r + "</r>\n";
                token += "</token>\n";

                this.poradi = 1;
                setCount(1);

                //Zapsáni tokenu na kartu
                sw.Write(token);

                sw.Close();
                file.Close();  
            }
            else        //Jestliže je soubor vytvořený.
            {
                //Otevře soubor TokenList.xml a přida nový token za poslední token v souboru
                FileStream file = new FileStream("C:/Data/TokenList.xml", FileMode.Append, FileAccess.Write);
                StreamWriter sw = new StreamWriter(file);

                this.poradi = poradi + 1;

                //Do proměnne 'token' se uloži všechny potřebné hodnoty. Text je formován do vzheldu XML dokumentu.
                string token = "";
                token += "<token id=\"" + this.poradi + "\">\n";
                token += "\t<a>" + token_a + "</a>\n";
                token += "\t<sigPA>" + sig_PA + "</sigPA>\n";
                token += "\t<r>" + r + "</r>\n";
                token += "</token>\n";

                //Zapsaní všech tokenů na kartu
                sw.Write(token);

                sw.Close();
                file.Close();   
            }   
        }

        //----------------------------------------------------------------------------
        //Metoda sloužící pro uložení 
        //----------------------------------------------------------------------------
        public void PutOnCard_param(string c, int[] w, int[] q, int mAP)
        {
            setC(c);
            setW(w);
            setQ(q);
            setMAP(mAP);
        }

        //----------------------------------------------------------------------------
        //Metoda sloužící na ziskani hodnot ze souboru TokenList.xml
        //----------------------------------------------------------------------------
        public string GetFromCard_token()
        {
            string token = "";
            string t_a = "";
            string t_sigPA = "";

            if (!File.Exists("C:/Data/TokenList.xml"))
            {
                token = "";
            }
            else 
            {
                StreamReader sReader = new StreamReader("C:/Data/TokenList.xml");
                XmlTextReader xr = new XmlTextReader(sReader);
                
                while (xr.Read())
                {
                    if (xr.Name == "token" && xr.HasAttributes == true)
                    {
                        if (xr.GetAttribute(0) == getCount().ToString())
                        {
                            xr.Read();
                            t_a = xr.ReadElementString("a");
                            t_sigPA = xr.ReadElementString("sigPA");
                            setT_r(xr.ReadElementString("r"));
                            break;
                        }
                    }
                }
                
                //token je v pořadí: c a sigPA
                token = getC() + " " + t_a + " " + t_sigPA; 
                
                setCount(getCount() + 1);   //nastav ukazatel na další volný token
            }
            return token;
        }

        //----------------------------------------------------------------------------
        //Metoda sloužící pro získání odezvy na náhodné číslo 'randE'
        //----------------------------------------------------------------------------
        public int[] GetFromCard_eResponse(int[] randE)
        {
            //Vytvočíme instanci třídy pro počítání s velkými čísly
            IntMath sm = new IntMath();

            //Převedení proměnné 't_r' ze stringu na int[]
            int[] r = new int[getT_r().Length];
            for (int i = 0; i <= getT_r().Length - 1; i++)
            {
                r[i] = getT_r()[i] - '0';
            }

            //Výpočet odezvy na náhodnou hodnotu 'randE':  (e*w+r)mod q
            int[] ewMODq = sm.MontgomeryInt(randE, getW(), getQ(), getMAP());
            int[] vysledek = sm.SoucetInt(ewMODq, r);
            int[] z;
            if (sm.UrciVetsiInt(vysledek, getQ()) == vysledek)
            {
                z = sm.RozdilInt(vysledek, getQ());
            }
            else
            {
                z = vysledek;
            }
            return z; 
        }
    }
}

