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


namespace LogoApp
{
    public partial class Form1 : Form
    {
        public Form1() // konstruktor okna aplikace
        {
            InitializeComponent();
            sada = new Sada();
            databaze = new Databaze();
            tabulka.Columns.Add("Slova",typeof(string));
            tabulka.Columns.Add("Spravnost", typeof(int));
            tabulka.Columns.Add("Nahravka", typeof(string));

            button4.Text = char.ConvertFromUtf32(0x2190);
            button5.Text = char.ConvertFromUtf32(0x2192);

            #region Prihlaseni uzivatele
            while (string.IsNullOrEmpty(uzivatel)) // zobrazeni okna pro prihlaseni uzvatele pri spusteni aplikace. Pokud uzivatel nevyplni uzivatelske cislo a klikne na tlacitko OK, vyskoci chybova hlaska.
            {
                Form2 loginDialog = new Form2();
                loginDialog.btnOk.DialogResult = DialogResult.OK;
                if (loginDialog.ShowDialog(this) == DialogResult.OK)
                {
                    uzivatel = loginDialog.txtUsNum.Text;
                    loginDialog.Dispose();

                    if (uzivatel == "")
                    {
                        MessageBox.Show("Je třeba zadat uživatelské číslo!", "Chyba", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }

                else
                {
                    Environment.Exit(1);
                }
            }
            #endregion

            popiskyTlacitka();

            for (int i = 2; i < 11; i++)
            {
                Label lb = Controls.Find("label" + Convert.ToString(i), true).FirstOrDefault() as Label;
                lb.Text = null;
            }
        }
       
        public DataTable tabulka = new DataTable(); // tabulka pro ukladani vysledku procvicovani
        public int tabIndex = -1; // promenna pro praci s tabulkou pro ukladani vysledku procvicovani
        public int index = 0; // promenna pro vyber hlasky
        public int pozice; //promenna pro urceni, kde se hlaska ve slove nachazi
        public int hotovo; //promena pro urceni, kdy lekci ukoncit
        public const int pocet_podsad = 2; // pocet podsad = pocet hlasek
        public string[] hlasky = new string[pocet_podsad] { "K", "L"};
        List<int> kontrola = new List<int>(); //pomocna promenna pro kontroluj, zda se odkryta cast odmeny neopakuje (nahodny vyber bez opakovani)
        List<string> odmeny = new List<string>() { "1.jpg", "2.jpg", "3.jpg" }; // seznam obrazku slouzicich jako odmena
        Sada sada; // konstruktor tridy Sada
        Slovo slovo; // konstruktor tridy Slovo
        Databaze databaze; // konstruktor tridy Databaze
        public string uzivatel; //promenna pro ulozeni uzivatelskeho cisla
        public string nazev_nahravky;
        

        private NAudio.Wave.WaveIn sourceStream = null; // promenna pro ulozeni dat z mikrofonu behem nahravani
        private NAudio.Wave.WaveFileWriter waveWriter = null; // promenna pro ulozeni nahravky vyslovnosti uzivatele do souboru .wav
        private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
        {
            if (waveWriter == null) return;
            waveWriter.WriteData(e.Buffer, 0, e.BytesRecorded);
            waveWriter.Flush();
        }
        
        private void inicializace() //inicializace pri vybrani nove hlasky a jeji pozice ve slove
        {
            if (tabulka.Rows.Count > 0)
            {
                tabulka.Clear();
            }

            tabulka.TableName = hlasky[index] + Convert.ToString(pozice);

            hotovo = 0;

            odmenaObr();
            
            Array.ForEach(Directory.GetFiles(Application.StartupPath + "\\Nahr\\"), File.Delete); //smazani vsech nahravek vyslovnosti uzivatele z predchoziho procvicovani
        }

        private void popiskyTlacitka() // metoda pro aktualizaci popisku tlacitek pro vyber umisteni hlasky ve slove
        {
            butJedna.Text = hlasky[index]+"__";
            butDva.Text = "_" + hlasky[index] + "_";
            butTri.Text = "__" + hlasky[index];
        }

        private void nacteniSlova(int pozice) // metoda pro nacteni nahodne vybraneho slova a pro jeho pridani do tabulky pro ukladani vysledku procvicovani
        {
            switch (pozice) //pozice = 1 - hlaska na zacatku slova | pozice = 2 - hlaska uprostred slova | pozice = 3 - hlaska na konci slova;
            {
                case 1:
                    slovo = sada.GetPod(index).Jedna.Dalsi();
                    break;
                case 2:
                    slovo = sada.GetPod(index).Dva.Dalsi();
                    break;
                case 3:
                    slovo = sada.GetPod(index).Tri.Dalsi();
                    break;
                default:
                    slovo = sada.GetPod(index).Jedna.Dalsi();
                    break;
            }

            label1.Text = slovo.Text;
            pictureBox1.Load(slovo.Obr);

            DataRow[] radky = tabulka.Select("Slova = '" + slovo.Text + "'"); // vyhleda radek s prave nactenym slovem
            if (radky.Count() > 0) //jestlize tabulka radek s danym slovem jiz obsahuje
            {
                tabIndex = tabulka.Rows.IndexOf(radky[0]); // cislo radku, na kterem se prave nactene slovo nachazi
            }else
            {
                tabulka.Rows.Add(slovo.Text, 1); // prida radek se slovem do tabulky a spravnost nastavi na 1
            }
            waveWriter = null;
            butPlay.Enabled = false;
            butAno.Enabled = false;
            butNe.Enabled = false;
        }
  
        private void jeKonec() // metoda pro vyhodnoceni, zda uz bylo zobrazeno vsech 9 slov jedne procvicovaci lekce
        {
            if (hotovo == 9) // pokud ano, odesle vysledky procvicovani na server, zobrazi gratulaci a ceka na vyber dalsi lekce
            {
                //tabulka.WriteXml(Application.StartupPath + "\\" + DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss_") + hlasky[index] + Convert.ToString(pozice) + ".xml"); // xml soubor pro kontrolu ulozenych vysledku
                MessageBox.Show("Procvičování ukončeno!", "Gratuluji!");
                butRec.Enabled = false;
                butPlay.Enabled = false;
                butAno.Enabled = false;
                butNe.Enabled = false;

                try
                {
                    if (databaze.JePripojenoSSH() != true) // pred odeslani vysledku prvniho procvicovani se aplikace pripoji k serveru pomoci SSH tunelu i k MySQL serveru
                    {
                        databaze.PripojSSH();
                        databaze.Pripoj();
                    }
                    foreach (DataRow row in tabulka.Rows)
                    {
                        databaze.Vloz(uzivatel, hlasky[index] + Convert.ToString(pozice), row[0].ToString(), row[1].ToString(), row[2].ToString()); // upload dat z tabulky do databaze
                        databaze.NahrajSoubor(Application.StartupPath + "\\Nahr\\" + row[2].ToString()); // upload nahravek uzivatelovi vyslovnosti na FTP server
                    }
                    MessageBox.Show("Výsledky procvičování úspěšně odeslány!", "Odeslání do databáze!");

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                         
            }
            else // pokud ne, nahodne vybere dalsi slovo z lekce
            {
                nacteniSlova(pozice);
            }
        }
      
        private void odmenaObr() // metoda pro nahodny vyber odmenovaciho obrazku (ze slozky Odm) a jeho skryti
        {
            for (int i = 2; i < 11; i++)
            {
                Label lb = Controls.Find("label" + Convert.ToString(i), true).FirstOrDefault() as Label;
                lb.Visible = true;
            }

            Random rnd = new Random();
            int vyber = rnd.Next(odmeny.Count);

            tableLayoutPanel1.BackgroundImage = Image.FromFile(Application.StartupPath + "\\Odm\\" +  odmeny[vyber]);      
        }

        private void odmenaZobraz() //metoda pro odkryti nahodne casti motivacniho obrazku
        {
            Random rnd = new Random();
            int vyber = rnd.Next(2, 11);

            while (kontrola.Contains(vyber))
            {
                vyber = rnd.Next(2, 11);              
            }

            kontrola.Add(vyber);
            Label lb = Controls.Find("label" + Convert.ToString(vyber), true).FirstOrDefault() as Label;
            lb.Visible = false;
        }

        #region Tlacitka pro vyber hlasky a jeji pozice ve slove
        private void butJedna_Click(object sender, EventArgs e) // pri stisknuti tlacitka pro vyber procvicovani hlasky na zacatku slova 
        {                                 
            kontrola.Clear();
            pozice = 1;
            inicializace();
            nacteniSlova(pozice);
            butRec.Enabled = true;

        }

        private void butDva_Click(object sender, EventArgs e) // pri stisknuti tlacitka pro vyber procvicovani hlasky uprostred slova
        {
            kontrola.Clear();
            pozice = 2;
            inicializace();
            nacteniSlova(pozice);
            butRec.Enabled = true;
        }

        private void butTri_Click(object sender, EventArgs e) // pri stisknuti tlacitka pro vyber procvicovani hlasky na konci slova 
        {
            kontrola.Clear();
            pozice = 3;
            inicializace();
            nacteniSlova(pozice);
            butRec.Enabled = true;
        }
        #endregion

        private void pictureBox1_Click(object sender, EventArgs e) // pri kliknuti na obrazek znazornujici dane slovo dojde k prehrani spravne vyslovnosti slova
        {
            if (pictureBox1.Image != null)
            {
                SoundPlayer vzor = new SoundPlayer(slovo.Zvuk);
                vzor.Play();
            }
        }

        private void butRec_CheckedChanged(object sender, EventArgs e) // pri prvnim kliknuti na tlacitko pro nahrani vyslovnosti uzivatele dojde k zahajeni nahravani. Tlacitko je dvoustavove
        {
            nazev_nahravky = uzivatel + DateTime.Now.ToString("-dd/M/yyyy-HH-mm-ss") + ".wav";

            if (butRec.Checked) // pri prvnim kliknuti dojde ke spusteni nahravani
            {
                butRec.BackColor = Color.Red;
                butPlay.Enabled = false;
                butAno.Enabled = false;
                butNe.Enabled = false;
                button4.Enabled = false;
                button5.Enabled = false;
                butJedna.Enabled = false;
                butDva.Enabled = false;
                butTri.Enabled = false;
                
                sourceStream = new NAudio.Wave.WaveIn();
                sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, 1);

                sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(sourceStream_DataAvailable);
                waveWriter = new NAudio.Wave.WaveFileWriter(Application.StartupPath + "\\Nahr\\" + nazev_nahravky, sourceStream.WaveFormat);

                sourceStream.StartRecording();
                tabulka.Rows[tabulka.Rows.Count - 1][2] = nazev_nahravky; //k poslednimu slovu v tabulce prida nahravku
            }
            else // pri druhem kliknuti dojde k ukonceni nahravani
            {
                butRec.BackColor = Color.White;

                sourceStream.StopRecording();
                sourceStream.Dispose();
                sourceStream = null;
                waveWriter.Dispose();

                butPlay.Enabled = true;
                button4.Enabled = true;
                button5.Enabled = true;
                butJedna.Enabled = true;
                butDva.Enabled = true;
                butTri.Enabled = true;
            }
        }

        private void butPlay_Click(object sender, EventArgs e) // pri kliknuti na tlacitko pro prehrani vyslovnosti uzivatele ji prehraje
        {
            SoundPlayer nahravka = new SoundPlayer(waveWriter.Filename);
            nahravka.Play();
            butAno.Enabled = true;
            butNe.Enabled = true;
        }

        #region Tlacitka pro prochazeni mezi hlaskami
        private void button4_Click(object sender, EventArgs e) // pri kliknuti na leve tlacitko dojde ke zmenseni promenne index a k aktualizaci popisku tlacitek pro vyber umisteni hlasky ve slove
        {
            index--;
            if (index < 0 )
            {
                index = pocet_podsad-1;
            }
            popiskyTlacitka();
        }

        private void button5_Click(object sender, EventArgs e) // pri kliknuti na prave tlacitko dojde ke zvetseni promenne index a k aktualizaci popisku tlacitek pro vyber umisteni hlasky ve slove
        {
            index++;
            if (index == pocet_podsad)
            {
                index = 0;
            }
            popiskyTlacitka();
        }
        #endregion

        private void butNe_Click(object sender, EventArgs e) // pri kliknuti na tlacitko pro zaporne hodnoceni vyslovnosti uzivatele 
        {
            if (tabIndex < 0) // prave zobrazene slovo bylo zaporne ohodnoceno poprve - oznaci ho jako spatne vyslovene a smaze jej ze seznamu jiz procvicenych slov
            {
                tabulka.Rows[tabulka.Rows.Count-1][1] = 0; // prave zobrazene slovo oznaci jako spatne vyslovene 
                switch (pozice)
                {
                    case 1:
                        sada.GetPod(index).Jedna.SmazPosledni();
                        break;
                    case 2:
                        sada.GetPod(index).Dva.SmazPosledni();
                        break;
                    case 3:
                        sada.GetPod(index).Tri.SmazPosledni();
                        break;
                    default:
                        sada.GetPod(index).Jedna.SmazPosledni();
                        break;
                }
            }
            else // prave zobrazene slovo bylo zaporne ohodnoceno podruhe
            {
                hotovo++;
                tabIndex = -1;
            }

            jeKonec();
        }

        private void butAno_Click(object sender, EventArgs e)  // pri kliknuti na tlacitko pro kladne hodnoceni vyslovnosti uzivatele
        {
            if (tabIndex >= 0) // slovo bylo nacteno podruhe
            {
                tabulka.Rows[tabIndex][1] = 1; //posledni (prave zobrazene) slovo oznaci jako spravne vyslovene
                tabIndex = -1;
            }

            hotovo++;
            odmenaZobraz();
            jeKonec();
        }

        private void Form1_HelpButtonClicked(object sender, CancelEventArgs e) // pri kliknuti na tlacitko napovedy zobrazi html napovedu v novem okne
        {
            Help.ShowHelp(this, Application.StartupPath + "\\Manual\\LogoApp Manual.chm");
        }
    }
}
