using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Turing
{
    //TODO: własne wyjątki

    public class Czwórka /*: Object*/
    {
        public char PoczątkowyStanGłowicy;
        public char PoczątkowyStanTaśmy;
        public char KońcowyStanTaśmyLubKomenda;
        public char KońcowyStanGłowicy;

        public Czwórka(char początkowyStanGłowicy, char początkowyStanTaśmy, char końcowyStanTaśmyLubKomenda, char końcowyStanGłowicy)
        {
            PoczątkowyStanGłowicy = początkowyStanGłowicy;
            PoczątkowyStanTaśmy = początkowyStanTaśmy;
            KońcowyStanTaśmyLubKomenda = końcowyStanTaśmyLubKomenda;
            KońcowyStanGłowicy = końcowyStanGłowicy;
            if (!Sprawdź(this)) throw new Exception("Błędne znaki inicjujące stan czwórki");
        }

        public Czwórka(string czwórka)
            : this(czwórka[0], czwórka[1], czwórka[2], czwórka[3])
        {
            if (czwórka.Length != 4) throw new Exception("Nieodpowiedni łańcuch inicjujący stan czwórki");
        }

        public static bool Sprawdź(Czwórka czwórka)
        {
            bool wynik =
                char.IsLetter(czwórka.PoczątkowyStanGłowicy) && char.IsLower(czwórka.PoczątkowyStanGłowicy) &&
                char.IsLetter(czwórka.PoczątkowyStanTaśmy) && char.IsUpper(czwórka.PoczątkowyStanTaśmy) &&
                char.IsLetter(czwórka.KońcowyStanTaśmyLubKomenda) && char.IsUpper(czwórka.KońcowyStanTaśmyLubKomenda) &&
                char.IsLetter(czwórka.KońcowyStanGłowicy) && char.IsLower(czwórka.KońcowyStanGłowicy);
            return wynik;
        }

        public override string ToString()
        {
            return "" + PoczątkowyStanGłowicy + PoczątkowyStanTaśmy + KońcowyStanTaśmyLubKomenda + KońcowyStanGłowicy;            
        }
    }

    //TODO: osobne pliki dla klas
    public class Program
    {
        private List<Czwórka> kod = null;

        public Program(List<Czwórka> kod)
        {
            if (kod == null) throw new Exception("Nie można utworzyć programu bez kodu");
            if (kod.Count == 0) throw new Exception("Kod musi zawierać linie");
            this.kod = kod;
            //TODO: this.kod = kod ?? throw new Exception("kod nie może być null");
        }

        public static Program Wczytaj(string ścieżkaPlikuProgramu)
        {
            string[] linie = File.ReadAllLines(ścieżkaPlikuProgramu);
            List<Czwórka> czwórki = new List<Czwórka>();
            foreach (string linia in linie)
            {
                czwórki.Add(new Czwórka(linia));
            }
            Turing.Program program = new Turing.Program(czwórki);
            return program;
        }

#if DEBUG
        public List<Czwórka> Kod //własność
        {
            get
            {
                return kod;
            }
        }
#endif
    }
}
