#define DEBUG_THE_SHIT

using System;
using System.IO;


class CoolShrank
{
    
    // Dieser Pfad geht natürlich nur unter Linux/Unix
    const string strContentPath = "/home/cbx/.coolshrankrc";
    const int DatensatzName = 0, DatensatzAnzahl = 1;
    const int MAX_CONTENT_TYPE = 4;
    
    // Hilfs-Enums zur Indizierung des Schrankinhalts
    // wird eigentlich bisher nicht gebraucht
    enum ShrankContent {Bier,Wein,Cola,Pizza};
    
    // Namen und Anzahl des Inhalts als Array
    static readonly string[] astrContentName = new string[MAX_CONTENT_TYPE]; // = {"Bier","Wein","Cola","Pizza"};
    static int[] anContentAmount = new int[MAX_CONTENT_TYPE]  {10,2,5,3};

//***********************************************************************
// Main()
    
    public static void Main(string[] args)
        {
        // Sicheren Grundzustand herstellen
        ShrankFill();
        
        // Laden, wenns das File nicht gibt, kommen die Defaults zum Zug
        ContentsLoad(strContentPath);
        
#if DEBUG_THE_SHIT
        // noch mal Inventar anzeigen
        for (int i=0; i < astrContentName.Length; i++ )
            Console.WriteLine("We got {0} {1}", anContentAmount[i], astrContentName[i]);
#endif      

        // Mailadresse abfragen
        if (userAuth())
            {
            MainMenu();
            }
        else
            {
            Console.WriteLine("==> Login failed :-P");
            }
            
        // speichern    
        ContentsSave(strContentPath);
        return;

        }
        

//***********************************************************************
// CoolShrankinhalt in ein File dumpen
    public static void ContentsSave(string strPath)
        {
        StreamWriter outStream;
        
        try 
            {
            outStream = new StreamWriter(strPath);
            }
        // generischer Catch. Wenn hier was nicht klappt, koennen wir wenig tun...  
        catch (Exception ex)
            {
            Console.WriteLine("Shit has happened: {0}",ex.Message);
            throw;
            }
            
        // geht, wenns gleich viele Namen wie Contents gibt 
        for (int i = 0; i < anContentAmount.Length; i++)
            {
            outStream.WriteLine("{0}={1}", astrContentName[i], anContentAmount[i]);
            }
        outStream.Close();  
        }
        

//***********************************************************************
// CoolShrankinhalt aus File holen      
    public static void ContentsLoad(string strPath)
        {

        FileInfo fiTextFile;
        StreamReader inStream;
        
        try 
            {
            fiTextFile = new FileInfo(strPath);
            inStream = fiTextFile.OpenText();
            }
        // einzig handelbarer Fall: Das file gibts noch nicht => defaults.  
        catch (FileNotFoundException ex)
            {
            Console.WriteLine("File not found, filling to defaults...");
            return;
            }
        
            
        string strLine;
        string[] astrPart;
        
        // Wir verwenden den StreamReader und lesen zeilenweise
        for (int i=0; (strLine = inStream.ReadLine()) != null; i++)
            {           

#if DEBUG_THE_SHIT
            Console.Write("Zeile {0}: >{1}< ==>",i+1,strLine);
#endif
            
            // mit string.Split() den String am "=" auftrennen
            astrPart = strLine.Split('=');
            // Die Split() Variante kommt mit Spaces um das "=" nicht so gut zurecht...
            // ...deshalb werden die noch abgeschnitten
            astrPart[DatensatzName] = astrPart[DatensatzName].Trim(); 
            astrPart[DatensatzAnzahl] = astrPart[DatensatzAnzahl].Trim();
             
#if DEBUG_THE_SHIT
            Console.WriteLine(" {0} : {1} ",astrPart[DatensatzName], 
                                            astrPart[DatensatzAnzahl]);
#endif          

            // unabhängig von der Reihenfolge identifizieren heisst...
            // fuer jede Zeile mit allen bekannten Namen vergleichen
            // und im Matching-Fall den Wert zuweisen (ACHTUNG: Nicht effizient!) 
            for (int nContent = 0; nContent < anContentAmount.Length; nContent++)
                {
                if (astrContentName[i] == astrPart[DatensatzName])
                    {
                    anContentAmount[i] = Int32.Parse(astrPart[DatensatzAnzahl]);
                    } 
                }
            }
        
        inStream.Close();
        
        return; 
    }


//***********************************************************************
// Legitimen User verifizieren      
// Eine gueltige Mailadresse hat 0 Spaces, ein At und mindestens einen Punkt
    public static bool userAuth()
        {
        int  nSpaces, nAts, nDots;
        string strEmailAdr;

        nSpaces = nAts = nDots = 0;

        Console.Write("Entern Sie Ihre valide Emil-Adresse: ");
        strEmailAdr = Console.ReadLine(); 

        // mit foreach() kann auch der containertyp "string" 
        // in einzelne zeichen zerlegt werden.
        // (char ist in C# uebrigens 16 bittig => Unicode)
        foreach (char c in strEmailAdr)
          {
          switch (c)
            {
            case ' ':
              nSpaces++;
              break;
            
            case '@':
              nAts++;
              break;
            case '.':
              nDots++;
              break;
            }
          }
        return ( (0 == nSpaces) && (1 == nAts) && (nDots >= 1));
        }


//***********************************************************************
// CoolShrank Menue vorstellen
    public static void MainMenu()
        {
        int c=0;
        
        do
            {
            Console.WriteLine("***************");
            Console.WriteLine("Das Hauptmenue!");
            Console.WriteLine("***************\n");
          
            for (int i=0; i < anContentAmount.Length; i++)
                {
                if (anContentAmount[i] > 0)
                    {
                    // Die Entnahmetasten werden einfach numeriert
                    Console.Write("({0})...{1} ({2})\n", 
                                  i+1, astrContentName[i], anContentAmount[i]);
                    }
                }
                
            Console.Write("(q)... Ende\n");  
            Console.Write("\nIhre Wahl: ");  
          
            c = Console.Read(); 
            
            // wegen bufferung der console das <Return> einfach hinterherlesen,
            // damit es hinterher nicht stoert...
            Console.Read();
            
            // aus ASCII die Index berechnen '1' ==> 0, '2' ==> 1 usw
            int n = c - '1';
            
            // Entnahme fuer gueltige Inhalt
            if (n >=0 && n < anContentAmount.Length)
                {
                if (anContentAmount[n] > 0)
                    {
                    anContentAmount[n]--;
                    Console.WriteLine("Ein mal {0}, bittesehr!", astrContentName[n]);
                    }
                }
                
            // Die geheime Auffuell-Taste    
            if ('R' == c)
                {
                ShrankFill();
                Console.Write ("==> Miraculous refill happened...\n");        
                }
          
          }
        while ('q' != c);
        }

    public static void ShrankFill()
        {
        anContentAmount[0] = 10;
        anContentAmount[1] =  2;
        anContentAmount[2] =  5;
        anContentAmount[3] =  3;

        astrContentName[0] = "Bier";
        astrContentName[1] = "Wein";
        astrContentName[2] = "Cola";
        astrContentName[3] = "Pizza";
        }

} // class

syntax highlighted by Code2HTML, v. 0.9.1