using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;


// Bitte beachten Sie auch den Fortsetzungsband zu diesem Buch, falls
// Ihnen das Programmieren Spaß gemacht hat und Sie sich fortgeschritteneren 
// Themen zuwenden wollen. Alle Informationen zum Fortsetzungsband finden
// Sie auf der Website: www.tiefer-einsteigen.de 


namespace MyNotepad
{
    public partial class NotePadForm : Form
    {
        // Name der Anwendung, für Text der Titelleiste
        private string applicationName = "My Notepad";

        // Pfad der aktuellen Datei
        private string currentFile = "";

        // wurde TextBox geändert
        private bool isModified = false;

        
        public NotePadForm()
        {
            InitializeComponent();
            wordWrapToolStripMenuItem.Checked = tbEdit.WordWrap;
        }

        private void öffnenToolStripMenuItem_Click(object sender, EventArgs e)
        {

            // Prüfen, ob das aktuelle Dokument bereits gespeichert wurde
            checkModified(sender, e);

            dlgOpenFile.Filter = "Textdateien (*.txt)|*.txt|Alle Dateien(*.*)|*.*";
            dlgOpenFile.FilterIndex = 2;
            

            DialogResult dlgResult;
            dlgResult = dlgOpenFile.ShowDialog();
            if (dlgResult == DialogResult.Cancel)
                return;

            try
            {
                // Zeichen-Codierung ermitteln
                Encoding enc = DetectFileEncoding(dlgOpenFile.FileName);
                // Datei öffnen, die ausgewählt wurde
                StreamReader sr = new StreamReader(dlgOpenFile.FileName, enc);

                // komplette Datei einlesen und der Eigenschaft Text des TextBox-Steuerelements zuweisen 
                tbEdit.Text = sr.ReadToEnd();

                // Datei schließen
                sr.Close();

                // Flag neu initialisieren
                this.isModified = false;

                // Text der Titelleiste ändern
                this.Text = Path.GetFileName(dlgOpenFile.FileName) + " - " + this.applicationName;
                // Name der aktuellen Datei merken
                this.currentFile = dlgOpenFile.FileName;
            }

            catch (Exception err)
            {
                MessageBox.Show(err.Message, "Fehler aufgetreten", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }


        }

        /// <summary>
        /// Ermittelt die Bytereihenfolge einer Datei und gibt die ermittelte Zeichen-Codierung zurück.
        /// </summary>
        /// <param name="sFile">Pfad der Datei, die untersucht werden soll</param>
        /// <returns>Encoding</returns>
        private Encoding DetectFileEncoding(string sFile)
        {
            // Standardmäßig die Default-Codierung verwenden (Ansi)
            Encoding enc = Encoding.Default;

            // Bytereihenfolge-Markierung ermitteln, wenn vorhanden
            // a) die ersten vier Zeichen einlesen
            byte[] buffer = new byte[4];
            FileStream file = new FileStream(sFile, FileMode.Open);
            file.Read(buffer, 0, 4);
            file.Close();

            // b) Buffer untersuchen und lokale Variable zuweisen
            if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf)
                enc = Encoding.UTF8;
            else if (buffer[0] == 0xfe && buffer[1] == 0xff)
                enc = Encoding.Unicode;
            else if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff)
                enc = Encoding.UTF32;
            else if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
                enc = Encoding.UTF7;

            // Codierung zurückgeben 
            return enc;

        }

        private void tbEdit_TextChanged(object sender, EventArgs e)
        {
            this.isModified = true;
        }

        private void speichernunterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Eigenschaften des Dialogs initialisieren
            dlgSaveFile.Filter = "Textdateien (*.txt)|*.txt|Alle Dateien(*.*)|*.*";
            dlgSaveFile.FilterIndex = 2;

            // Dialogfeld anzeigen lassen
            DialogResult dlgResult;
            dlgResult = dlgSaveFile.ShowDialog();
            if (dlgResult == DialogResult.Cancel)
                return;

            try
            {
                // Dateinamen merken
                this.currentFile = dlgSaveFile.FileName;

                // StreamWriter-Objekt erstellen, als Codierung UFT8 verwenden
                StreamWriter sw = new StreamWriter(this.currentFile, false, Encoding.UTF8);

                // Inhalt der TextBox in Datei schreiben
                sw.Write(this.tbEdit.Text);

                // Datei wieder schließen
                sw.Close();

                // Geändert-Flag zurücksetzen
                this.isModified = false;

                // Titelleiste anpassen
                this.Text = Path.GetFileName(this.currentFile) + " - " + this.applicationName;
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message, "Fehler aufgetreten", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }

        private void speichernToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // noch kein Dateiname vorhanden?
            if (this.currentFile == "")
            {
                // neue Datei speichern lassen
                speichernunterToolStripMenuItem_Click(sender, e);
                return;
            }
            else
            {
                // Inhalt der TextBox unter bekanntem Dateinamen speichern
                try
                {
                    StreamWriter sw = new StreamWriter(this.currentFile, false, Encoding.UTF8);
                    sw.Write(this.tbEdit.Text);
                    sw.Close();
                }


                catch (Exception err)
                {
                    MessageBox.Show(err.Message, "Fehler aufgetreten",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                this.isModified = false;
            }

        }

        private void neuToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Prüfen, ob das aktuelle Dokument bereits gespeichert wurde
            checkModified(sender, e);

            // Aktuellen Dateinamen zurücksetzen
            this.currentFile = "";

            // Inhalt der TextBox löschen            
            this.tbEdit.Clear();

            // Titelleiste anpassen
            this.Text = this.applicationName;

            // Geändert-Flag zurücksetzen
            // Diese Anweisung MUSS nach dem Aufruf von this.tbEdit.Clear() stehen, da 
            // durch den Aufruf von Clear das Ereignis TextChanged ausgelöst wird und im
            // Eventhandler das Flag dann wieder auf true gesetzt wird
            this.isModified = false;

        }

        private void checkModified(object sender, EventArgs e)
        {
            // wenn aktuelles Dokument noch nicht gespeichert wurde
            if (this.isModified == true)
            {
                // Benutzer fragen, ob das Dokument gespeichert werden soll
                DialogResult dlgResult;
                dlgResult = MessageBox.Show("Möchten Sie das Dokument speichern?",
                                this.applicationName,
                                MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);

                // Wenn er auf Ja klickt
                if (dlgResult == DialogResult.Yes)
                {
                    // den Eventhandler für das Speichern aufrufen
                    // dieser kümmert sich dann um alles Weitere und ruft
                    // evtl. speichernunterToolStripMenuItem_Click auf, um einen
                    // Dateinamen anzufordern
                    speichernToolStripMenuItem_Click(sender, e);
                }
                // wenn er auf Nein klickt
                else
                {
                    // Geändert-Flag zurücksetzen
                    this.isModified = false;
                }
            }

        }

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

        private void NotePadForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            // Prüfen, ob das aktuelle Dokument bereits gespeichert wurde
            checkModified(sender, e);
        }

        private void alleauswählenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.tbEdit.SelectAll();
        }

        private void ausschneidenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.tbEdit.Cut();
        }

        private void kopierenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.tbEdit.Copy();
        }

        private void einfügenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.tbEdit.Paste();
        }

        private void infoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutMyNotepad aboutDlg = new AboutMyNotepad();
            aboutDlg.ShowDialog();
        }

        private void textSucheToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult dialogResult;
            SearchForm searchForm = new SearchForm();
            dialogResult = searchForm.ShowDialog();

            if (dialogResult == DialogResult.OK)
            {

                // Kontrollkästchen "Groß-/Kleinschreibung beachten" auswerten
                StringComparison stringComparison;
                if (searchForm.CaseSensitive == true)
                    stringComparison = StringComparison.CurrentCulture;
                else
                    stringComparison = StringComparison.CurrentCultureIgnoreCase;

                // Der Einfachheit halber immer ab Anfang der TextBox suchen
                int i = this.tbEdit.Text.IndexOf(searchForm.SearchText, 0, stringComparison);

                // Suchstring wurde in TextBox gefunden
                if (i >= 0)
                {
                    // Fundstelle in der TextBox markieren
                    this.tbEdit.Select(i, searchForm.SearchText.Length);
                }
                else
                {
                    MessageBox.Show("Der Suchtext wurde leider nicht gefunden.", this.applicationName,
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                }


            }

        }

        private void fontToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Neue Instanz von FontDialog erstellen
            FontDialog fontDialog = new FontDialog();

            // aktuelle Schriftart der TextBox an das Dialogfeld übergeben
            fontDialog.Font = this.tbEdit.Font;

            // wenn auf OK geklickt wurde, der TextBox die ausgewählte 
            // Schriftart zuweisen
            if (fontDialog.ShowDialog() == DialogResult.OK)
                this.tbEdit.Font = fontDialog.Font;

        }

        private void wordWrapToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Wert umkehren
            tbEdit.WordWrap = !tbEdit.WordWrap;

            // je nach Wert Häkchen im Menü ein- oder ausschalten
            wordWrapToolStripMenuItem.Checked = tbEdit.WordWrap;

        }
    }
}
