using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Net;
using System.Text.RegularExpressions;
using Code7248.word_reader;

// rozšířit seznam stopslov a předpon/přípon
//----------------------------------------------------------
// zredukovat množství dotazů na google - rozšířit seznam stopslov
// přidat do vyhledávání i porovnání s dokumentem (pokud je nastaveno automaticky porovnat), aby se vyhnulo spamování googlu
// rozdělit seznam stopslov na dva - jeden natvrdo v programu pro porovnání, druhý z texťáku pro hledání
//---------------------------------------------------------
// zkusit jestli funguje pro n=1
// přidat reset tlačítka
// zvýraznit shody v textu (optimálně odkazy mezi slovy)

namespace PlagSearcherPro
{
    public partial class Form1 : Form
    {
        // globální proměnné
        int num_of_pages_suspect = 0;                                               // počet stran podezřelého dokumentu (po filtraci)
        int num_of_words_suspect_total = 0;                                         // počet slov podezřelého dokumentu
        int num_of_words_suspect = 0;                                               // počet slov v podezřelém dokumentu (po čištění)
        int num_of_uniques_suspect = 0;                                             // počet unikátních slov v podezřelém dokumentu (lemmatizaci)
        Dictionary<string, bool> stopwords = new Dictionary<string, bool>();        // seznam stopslov
        Form2 BrowserForm = new Form2();                                            // prohlížeč výsledků
        string last_opened = "";                                                         // poslední otevřený dokument
        bool running = false;
        string[] files_to_do;

        // inicializace
        public Form1()
        {
            InitializeComponent();
            ComboFontStyle.SelectedIndex = 1;
            ComboClusterScoreLimit.SelectedIndex = 4;

            //Tvorba potřebných složek
            //download - zde se dočasně ukládají stažené zdroje
            //reports - slouží k dlouhodobému uchování výsledků vyhledávání
            if (!Directory.Exists("download"))
                Directory.CreateDirectory("download");
            if (!Directory.Exists("reports"))
                Directory.CreateDirectory("reports");

            // vytvoření seznamu stopslov
            CreateStopWordsList();

            File.AppendAllText("Error_log.txt", String.Format("#----- {0} -----#\r\n", DateTime.Now.ToString()));

            //Načtení nastavení uživatele
            IniReaderWriter iniprocessingunit = new IniReaderWriter();

            if (File.Exists("PlagSearcherPro_Config.ini"))
            {
                try
                {
                    iniprocessingunit.ReadIniFile("PlagSearcherPro_Config.ini");

                    CheckFilterOnOff.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("System", "FilterOn"));
                    RadioAutoFilter.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("System", "FilterAuto"));
                    RadioManualFilter.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("System", "FilterManual"));
                    CheckStartFilter.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("System", "FilterStart"));
                    CheckEndFilter.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("System", "FilterEnd"));
                    NumericStartFilter.Value = Convert.ToDecimal(iniprocessingunit.GetKeyValue("System", "FilterStartNum"));
                    NumericEndFilter.Value = Convert.ToDecimal(iniprocessingunit.GetKeyValue("System", "FilterEndNum"));
                    CheckCompare.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("System", "CompareNow"));
                    CheckShowSearch.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("System", "ShowSearch"));
                    this.Size = new System.Drawing.Size(Convert.ToInt32(iniprocessingunit.GetKeyValue("System", "WinWidth")), Convert.ToInt32(iniprocessingunit.GetKeyValue("System", "WinHeight")));
                    if (Convert.ToBoolean(iniprocessingunit.GetKeyValue("System", "Maximized")))
                        this.WindowState = FormWindowState.Maximized;

                    ComboFontStyle.SelectedIndex = Convert.ToInt32(iniprocessingunit.GetKeyValue("Settings", "FontStyle"));
                    NumericFontSize.Value = Convert.ToDecimal(iniprocessingunit.GetKeyValue("Settings", "FontSize"));
                    TrackNValue.Value = Convert.ToInt32(iniprocessingunit.GetKeyValue("Settings", "NValue"));
                    CheckCosSim.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("Settings", "CheckCos"));
                    CheckClusterScore.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("Settings", "CheckCluster"));
                    NumericCosSimLimit.Value = Convert.ToDecimal(iniprocessingunit.GetKeyValue("Settings", "CosLimit"));
                    ComboClusterScoreLimit.SelectedIndex = Convert.ToInt32(iniprocessingunit.GetKeyValue("Settings", "ClusterLimit"));

                    TrackSearchWords.Value = Convert.ToInt32(iniprocessingunit.GetKeyValue("Search", "SearchWords"));
                    TrackDownloadNum.Value = Convert.ToInt32(iniprocessingunit.GetKeyValue("Search", "DownloadLimit"));
                    TrackJumpWords.Value = Convert.ToInt32(iniprocessingunit.GetKeyValue("Search", "JumpWords"));
                    CheckLemmatize.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("Search", "CheckLemma"));
                    CheckManualInput.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("Search", "CheckManual"));
                    CheckSearchKeyWords.Checked = Convert.ToBoolean(iniprocessingunit.GetKeyValue("Search", "CheckKeyWords"));

                    if (File.Exists("Original.txt"))
                    {
                        num_of_pages_suspect = Convert.ToInt32(iniprocessingunit.GetKeyValue("Data", "SuspectPages"));
                        num_of_words_suspect = Convert.ToInt32(iniprocessingunit.GetKeyValue("Data", "SuspectWords"));
                        num_of_words_suspect_total = Convert.ToInt32(iniprocessingunit.GetKeyValue("Data", "SuspectWordsTotal"));
                        num_of_uniques_suspect = Convert.ToInt32(iniprocessingunit.GetKeyValue("Data", "SuspectUniques"));
                        last_opened = iniprocessingunit.GetKeyValue("Data", "SuspectPath");
                        if (String.Compare(last_opened, @"N/A") == 0)
                            last_opened = String.Empty;
                    }
                }
                catch (Exception ex)
                {
                    System.Media.SystemSounds.Hand.Play();
                    File.AppendAllText("Error_log.txt" ,ex.Message + "\r\n");
                    StatusText.Text = "Chyba: Nelze přečíst nastavení ze souboru PlagSearcherPro_Config.ini.";
                }
            }
        }

        // uložení nastavení při ukončení aplikace
        private void ApplicationEnds(object sender, FormClosingEventArgs e)
        {
            IniReaderWriter iniprocessingunit = new IniReaderWriter();

            //Ukládání současného nastavení
            try
            {
                // systém
                iniprocessingunit.AddNewSection("System");
                iniprocessingunit.AddNewKey("System", "FilterOn", CheckFilterOnOff.Checked.ToString());
                iniprocessingunit.AddNewKey("System", "FilterAuto", RadioAutoFilter.Checked.ToString());
                iniprocessingunit.AddNewKey("System", "FilterManual", RadioManualFilter.Checked.ToString());
                iniprocessingunit.AddNewKey("System", "FilterStart", CheckStartFilter.Checked.ToString());
                iniprocessingunit.AddNewKey("System", "FilterEnd", CheckEndFilter.Checked.ToString());
                iniprocessingunit.AddNewKey("System", "FilterStartNum", NumericStartFilter.Value.ToString());
                iniprocessingunit.AddNewKey("System", "FilterEndNum", NumericEndFilter.Value.ToString());
                iniprocessingunit.AddNewKey("System", "CompareNow", CheckCompare.Checked.ToString());
                iniprocessingunit.AddNewKey("System", "ShowSearch", CheckShowSearch.Checked.ToString());
                if (this.WindowState == FormWindowState.Maximized)
                    iniprocessingunit.AddNewKey("System", "Maximized", "True");
                else
                    iniprocessingunit.AddNewKey("System", "Maximized", "False");
                this.WindowState = FormWindowState.Normal;
                iniprocessingunit.AddNewKey("System", "WinWidth", this.Size.Width.ToString());
                iniprocessingunit.AddNewKey("System", "WinHeight", this.Size.Height.ToString());

                // nastavení
                iniprocessingunit.AddNewSection("Settings");
                iniprocessingunit.AddNewKey("Settings", "FontStyle", ComboFontStyle.SelectedIndex.ToString());
                iniprocessingunit.AddNewKey("Settings", "FontSize", NumericFontSize.Value.ToString());
                iniprocessingunit.AddNewKey("Settings", "NValue", TrackNValue.Value.ToString());
                iniprocessingunit.AddNewKey("Settings", "CheckCos", CheckCosSim.Checked.ToString());
                iniprocessingunit.AddNewKey("Settings", "CheckCluster", CheckClusterScore.Checked.ToString());
                iniprocessingunit.AddNewKey("Settings", "CosLimit", NumericCosSimLimit.Value.ToString());
                iniprocessingunit.AddNewKey("Settings", "ClusterLimit", ComboClusterScoreLimit.SelectedIndex.ToString());

                // vyhledávání
                iniprocessingunit.AddNewSection("Search");
                iniprocessingunit.AddNewKey("Search", "SearchWords", TrackSearchWords.Value.ToString());
                iniprocessingunit.AddNewKey("Search", "DownloadLimit", TrackDownloadNum.Value.ToString());
                iniprocessingunit.AddNewKey("Search", "JumpWords", TrackJumpWords.Value.ToString());
                iniprocessingunit.AddNewKey("Search", "CheckLemma", CheckLemmatize.Checked.ToString());
                iniprocessingunit.AddNewKey("Search", "CheckManual", CheckManualInput.Checked.ToString());
                iniprocessingunit.AddNewKey("Search", "CheckKeyWords", CheckSearchKeyWords.Checked.ToString());

                //data
                iniprocessingunit.AddNewSection("Data");
                iniprocessingunit.AddNewKey("Data", "SuspectPages", num_of_pages_suspect.ToString());
                iniprocessingunit.AddNewKey("Data", "SuspectWordsTotal", num_of_words_suspect_total.ToString());
                iniprocessingunit.AddNewKey("Data", "SuspectWords", num_of_words_suspect.ToString());
                iniprocessingunit.AddNewKey("Data", "SuspectUniques", num_of_uniques_suspect.ToString());
                if (!String.IsNullOrEmpty(last_opened))
                    iniprocessingunit.AddNewKey("Data", "SuspectPath", last_opened);
                else
                    iniprocessingunit.AddNewKey("Data", "SuspectPath", @"N/A");

                // uložení nastavení
                iniprocessingunit.RewriteIniFile("PlagSearcherPro_Config.ini");
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Chyba: Soubor nastavení PlagSearcherPro_Config.ini se nepodařilo vytvořit.";
            }
        }

        //Vypíná a zapíná nastavení manuální filtrace pro lepší přehlednost nastavení
        private void RadioAutoFilterCheck(object sender, EventArgs e)
        {
            if (RadioAutoFilter.Checked)
            {
                CheckStartFilter.Enabled = false;
                CheckEndFilter.Enabled = false;
                NumericStartFilter.Enabled = false;
                NumericEndFilter.Enabled = false;
            }
            else
            {
                CheckStartFilter.Enabled = true;
                CheckEndFilter.Enabled = true;
                NumericStartFilter.Enabled = true;
                NumericEndFilter.Enabled = true;
            }
        }

        //Mění pozici a velikost ovládání podle velikosti okna
        private void FormResize(object sender, EventArgs e)
        {
            int new_width = this.Size.Width / 2 - 26;
            int new_height = this.Size.Height - 186;

            GroupLeft.Width = new_width;
            GroupRight.Width = new_width;
            GroupLeft.Height = new_height;
            GroupRight.Height = new_height;
            GroupRight.Location = new Point(new_width+24, 123);
        }

        //Otevření podezřelého dokumentu
        private void ButtonOpenClick(object sender, EventArgs e)
        {
            //Aktualizace stavu
            if (CheckFilterOnOff.Checked)
                StatusText.Text = "Otevírám a filtruji dokument. Čekejte prosím.";
            else
                StatusText.Text = "Otevírám dokument. Čekejte prosím.";

            if (DialogOpenFile.ShowDialog() == DialogResult.OK)
            {
                // Získání cesty k souboru
                if (DialogOpenFile.FileNames.Length == 0)
                {
                    System.Media.SystemSounds.Hand.Play();
                    StatusText.Text = "Nebyl vybrán žádný dokument k otevření.";
                    return;
                }

                if (DialogOpenFile.FileNames.Length == 1)
                    this.Text = "PlagSearcherPro - manual";
                else
                    this.Text = "PlagSearcherPro - auto";

                files_to_do = DialogOpenFile.FileNames;

                last_opened = DialogOpenFile.FileNames[0];

                //převod cesty z absolutní na relativní
                Uri current_path = new Uri(Directory.GetCurrentDirectory()+"/");
                Uri target_path = new Uri(DialogOpenFile.FileNames[0]);
                string file_path = current_path.MakeRelativeUri(target_path).ToString();

                // pdftotext.exe nezvládne mezery v cestě k souboru
                if (file_path.Contains(' '))
                {
                    System.Media.SystemSounds.Hand.Play();
                    StatusText.Text = "Chyba: Cesta nebo název souboru obsahuje mezery.";
                    return;
                }

                //Převod souboru na text
                uint filter_first_pages = 0, filter_last_pages = 0;

                if (CheckStartFilter.Checked)
                    filter_first_pages = System.Convert.ToUInt32(NumericStartFilter.Value);
                if (CheckEndFilter.Checked)
                    filter_last_pages = System.Convert.ToUInt32(NumericEndFilter.Value);

                File.Delete("Original.txt");

                bool finished_ok = ConvertPDFtoText(file_path, "Original.txt", CheckFilterOnOff.Checked, RadioAutoFilter.Checked, filter_first_pages, filter_last_pages, true, false);

                if (finished_ok)
                {
                    if (!File.Exists("Original.txt"))
                    {
                        System.Media.SystemSounds.Hand.Play();
                        StatusText.Text = "Chyba: Filtrace dokumentu selhala. Zvolte prosím jinou metodu.";
                        return;
                    }

                    // zobrazení souboru
                    GroupLeft.Text = "Podezřelý dokument: \"" + Path.GetFileName(file_path) + "\"";
                    TextBoxSuspect.Text = File.ReadAllText("Original.txt", System.Text.Encoding.GetEncoding(28592));

                    StatusText.Text = "Otevření dokumentu dokončeno.";
                }
            }
            else
                StatusText.Text = "Otevření dokumentu zrušeno.";
        }

        //Změna stylu písma
        private void NumericFontChanged(object sender, EventArgs e)
        {
            TextBoxSuspect.Font = new Font(ComboFontStyle.SelectedItem.ToString(), Convert.ToSingle(NumericFontSize.Value));
            TextBoxSource.Font = new Font(ComboFontStyle.SelectedItem.ToString(), Convert.ToSingle(NumericFontSize.Value));
        }

        // Vyhledání zdrojů na internetu
        private void ButtonSearchClick(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(TextBoxSuspect.Text))
            {
                System.Media.SystemSounds.Hand.Play();
                StatusText.Text = "Chyba: Není otevřen žádný dokument.";
                return;
            }

            File.AppendAllText("Error_log.txt", "-- Vyhledávání -- \r\n");

            DisableEnableControls(false);

            for (int file_num = 0; file_num < files_to_do.Length; file_num++)
            {

                // inicializace progress baru
                StatusProgressBar.Value = 0;
                StatusProgressBar.Maximum = num_of_pages_suspect;
                StatusText.Text = "(1/4) Probíhá čištění textu. Čekejte prosím.";
                Application.DoEvents();

                DateTime begin_time = DateTime.Now;

                if (files_to_do.Length > 1)
                    CheckCompare.Checked = true;

                File.Delete("Cleaned.txt");
                File.Delete("Processed.txt");
                File.Delete("Ngrams.txt");
                string[] files = Directory.GetFiles("download");
                foreach (string file in files)
                    File.Delete(file);
                files = Directory.GetFiles("reports");
                foreach (string file in files)
                    File.Delete(file);
                files = Directory.GetFiles(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName));
                foreach (string file in files)
                {
                    if (file.IndexOf("Positives") != -1)
                        File.Delete(file);
                }
                Form fc = Application.OpenForms["Form2"];
                if (fc != null)
                    fc.Close();
                num_of_words_suspect = 0;

                Application.DoEvents();


                last_opened = DialogOpenFile.FileNames[file_num];

                //převod cesty z absolutní na relativní
                Uri current_path = new Uri(Directory.GetCurrentDirectory() + "/");
                Uri target_path = new Uri(DialogOpenFile.FileNames[file_num]);
                string file_path = current_path.MakeRelativeUri(target_path).ToString();

                // pdftotext.exe nezvládne mezery v cestě k souboru
                if (file_path.Contains(' '))
                {
                    System.Media.SystemSounds.Hand.Play();
                    File.AppendAllText("Error_log.txt", "Chyba: Cesta nebo název souboru obsahuje mezery.\r\n");
                    continue;
                }

                //Převod souboru na text
                uint filter_first_pages = 0, filter_last_pages = 0;

                if (CheckStartFilter.Checked)
                    filter_first_pages = System.Convert.ToUInt32(NumericStartFilter.Value);
                if (CheckEndFilter.Checked)
                    filter_last_pages = System.Convert.ToUInt32(NumericEndFilter.Value);

                File.Delete("Original.txt");

                bool ok_finished = ConvertPDFtoText(file_path, "Original.txt", CheckFilterOnOff.Checked, RadioAutoFilter.Checked, filter_first_pages, filter_last_pages, true, true);

                if (ok_finished)
                {
                    if (!File.Exists("Original.txt"))
                    {
                        System.Media.SystemSounds.Hand.Play();
                        File.AppendAllText("Error_log.txt", "Chyba: Filtrace dokumentu selhala.\r\n");
                        ConvertPDFtoText(file_path, "Original.txt", false, false, filter_first_pages, filter_last_pages, true, true);
                    }

                    // zobrazení souboru
                    GroupLeft.Text = "Podezřelý dokument: \"" + Path.GetFileName(file_path) + "\"";
                    TextBoxSuspect.Text = File.ReadAllText("Original.txt", System.Text.Encoding.GetEncoding(28592));
                }


                // čištění textu
                try
                {
                    StreamReader reader = new StreamReader("Original.txt", System.Text.Encoding.GetEncoding(28592));
                    string page = String.Empty;

                    while (LoadPage(ref page, ref reader))
                    {
                        Application.DoEvents();

                        File.AppendAllText(@"Cleaned.txt", CleanTextFile(page), System.Text.Encoding.GetEncoding(28592));
                    }

                    reader.Dispose();
                }
                catch (Exception ex)
                {
                    System.Media.SystemSounds.Hand.Play();
                    File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                    if (files_to_do.Length == 1)
                        StatusText.Text = "Chyba: Nastala chyba při čištění textového souboru.";
                    File.Delete("Cleaned.txt");
                    continue;
                }

                StatusProgressBar.Value = StatusProgressBar.Maximum;
                Application.DoEvents();

                // zjednodušení textu
                StatusProgressBar.Value = 0;
                StatusProgressBar.Maximum = 1;
                StatusText.Text = "(2/4) Probíhá lematizace textu. Čekejte prosím.";
                Application.DoEvents();

                // zjednodušení textu
                if (!LemmatizeFile("Cleaned.txt", "Processed.txt"))
                {
                    File.Delete("Processed.txt");
                    continue;
                }

                StatusProgressBar.Value = StatusProgressBar.Maximum;
                Application.DoEvents();

                //sestavení stringů, které se budou vyhledávat
                StatusProgressBar.Value = 0;
                StatusProgressBar.Maximum = num_of_words_suspect / TrackSearchWords.Value;
                StatusText.Text = "(3/4) Probíhá sestavování slov pro vyhledávání. Čekejte prosím.";
                Application.DoEvents();

                List<string> search_strings = new List<string>();
                int word_count = 0;
                int ignore_words = 0;
                string source_path, word_read = "", search_string = "";
                //pokud proběhla lematizace
                if (CheckLemmatize.Checked)
                    source_path = "Processed.txt";
                else
                    source_path = "Cleaned.txt";
                Application.DoEvents();

                // vytáhnutí unikátních slov a vybrání klíčových slov pokud nastaveno
                Dictionary<string, uint> unique_words = new Dictionary<string, uint>();

                if (!LoadUniqueWords("Processed.txt", ref unique_words))
                {
                    continue;
                }
                num_of_uniques_suspect = unique_words.Count + stopwords.Count;
                Application.DoEvents();

                if (CheckSearchKeyWords.Checked)
                {
                    int count = 0;

                    foreach (KeyValuePair<string, uint> word in unique_words)
                    {
                        if (count == TrackSearchWords.Value)
                        {
                            search_strings.Add(search_string);
                            search_string = "";
                            count = 0;
                        }
                        else if ((Convert.ToDouble(word.Value) / num_of_uniques_suspect) > 0.01)
                        {
                            search_string += word.Key + " ";
                            count++;
                        }
                        Application.DoEvents();
                    }
                }


                if (!CheckManualInput.Checked && !CheckSearchKeyWords.Checked)
                {
                    try
                    {
                        using (StreamReader reader = new StreamReader(source_path, Encoding.GetEncoding(28592)))
                        {
                            do
                            {
                                while (reader.Peek() != ' ')
                                {
                                    word_read += Convert.ToChar(reader.Read());
                                }
                                reader.Read();

                                // nabere tolik slov kolik je v nastavení a přidá je jako jednu položku k vyhledání
                                if (word_count < TrackSearchWords.Value)
                                {
                                    if (ignore_words == TrackJumpWords.Value)
                                    {
                                        search_string += word_read + " ";
                                        word_count++;
                                        ignore_words = 0;
                                    }
                                    else
                                        ignore_words++;
                                }
                                else
                                {
                                    search_strings.Add(search_string);
                                    search_string = "";
                                    word_count = 0;
                                    StatusProgressBar.Value++;
                                    Application.DoEvents();
                                }

                                word_read = "";
                                Application.DoEvents();
                            }
                            while (reader.Peek() != -1);

                            if (!String.IsNullOrEmpty(search_string))
                                search_strings.Add(search_string);
                        }
                    }
                    catch (Exception ex)
                    {
                        System.Media.SystemSounds.Hand.Play();
                        File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                        StatusText.Text = "Chyba: Nastala chyba při sestavování slov pro vyhledávání.";
                        File.Delete("Cleaned.txt");
                        File.Delete("Processed.txt");
                        continue;
                    }
                }

                if (CheckManualInput.Checked)
                    search_strings.Add(TextBoxManualInput.Text);

                // vytvoření n-gramů pro hledaný dokument, pokud je povoleno porovnávat
                Dictionary<string, int> word_table = new Dictionary<string, int>();
                Dictionary<string, int> word_table_backup = new Dictionary<string, int>();
                int suspect_ngrams_number = 0;
                Application.DoEvents();
                if (CheckCompare.Checked)
                {
                    suspect_ngrams_number = CreateNGrams("Processed.txt", "Ngrams.txt", TrackNValue.Value, ref word_table);
                }
                Application.DoEvents();

                // uložení kopie n-gramů
                foreach (KeyValuePair<string, int> item in word_table)
                {
                    word_table_backup.Add(String.Copy(item.Key), item.Value);
                }

                StatusProgressBar.Value = StatusProgressBar.Maximum;
                Application.DoEvents();

                // vyhledávání a stahování zdrojů
                StatusProgressBar.Value = 0;
                StatusProgressBar.Maximum = search_strings.Count;
                if (CheckCompare.Checked)
                    StatusText.Text = String.Format("(4/4) Probíhá {0} vyhledávání, stahování a porovnání zdrojů. Čekejte prosím.", search_strings.Count);
                else
                    StatusText.Text = String.Format("(4/4) Probíhá {0} vyhledávání a stahování zdrojů. Čekejte prosím.", search_strings.Count);
                Application.DoEvents();

                // vyhledávání a stahování zdrojů
                WebBrowser webSearcher = new WebBrowser();
                List<string> list_of_results = new List<string>();
                Dictionary<string, bool> search_output = new Dictionary<string, bool>();
                List<KeyValuePair<string, bool>> search_temp_output = new List<KeyValuePair<string, bool>>();
                List<string> links_to_source = new List<string>();
                int download_fails = 0, counter = 0, last_downloaded = -1;
                word_count = 0;

                // pro každý prvek v seznamu stringů k vyhledání
                for (int j = 0; j < search_strings.Count; j++)
                {
                    // získáme odpověď z google
                    webSearcher.Url = new Uri("https://www.google.cz/search?q=" + search_strings[j]);
                    while (webSearcher.ReadyState != WebBrowserReadyState.Complete)
                    {
                        Application.DoEvents();
                        if (!running)
                        {
                            DisableEnableControls(true);
                            StatusText.Text = "Vyhledávání zrušeno.";
                            return;
                        }
                    }

                    // dostaneme seznam adres
                    list_of_results = GetUrls(webSearcher.DocumentText);

                    // vybereme pouze adresy, které nebyly dosud staženy (nenachází se v search_output)
                    for (int i = list_of_results.Count - 1; i >= 0; i--)
                    {
                        if (!search_output.ContainsKey(list_of_results[i]))
                        {
                            search_temp_output.Add(new KeyValuePair<string,bool>(list_of_results[i], false));
                        }
                        Application.DoEvents();
                    }
                    list_of_results.Clear();

                    last_downloaded = word_count;

                    //stažení dosud nestažených adres
                    using (WebClient Client = new WebClient())
                    {
                        Client.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0)");
                        string extension, address;
                        counter = 0;

                        for (int i = search_temp_output.Count - 1; i >= 0; i--)
                        {
                            Application.DoEvents();
                            if (!running)
                            {
                                DisableEnableControls(true);
                                StatusText.Text = "Vyhledávání zrušeno.";
                                return;
                            }

                            if (search_temp_output.ElementAt(i).Value)
                                break;

                            if (!CheckSearchKeyWords.Checked && !CheckManualInput.Checked && counter == TrackDownloadNum.Value)
                            {
                                search_temp_output.RemoveAt(i);
                                continue;
                            }

                            search_temp_output[i] = new KeyValuePair<string, bool>(search_temp_output[i].Key, true);
                            address = search_temp_output.ElementAt(i).Key;
                            extension = Path.GetExtension(address);

                            if (extension != String.Empty && extension.Length < 5)
                            {
                                try
                                {
                                    Client.DownloadFileAsync(new Uri(address), "download/file" + word_count.ToString() + extension);
                                    DateTime timeout = DateTime.Now;

                                    while (Client.IsBusy)
                                    {
                                        if ((DateTime.Now - timeout).Seconds > 50)
                                        {
                                            Client.CancelAsync();
                                            while (IsFileInUse(new FileInfo("download/file" + word_count.ToString() + extension)))
                                            { }
                                            File.Delete("download/file" + word_count.ToString() + extension);
                                            throw new TimeoutException();
                                        }
                                    }

                                    if (new FileInfo("download/file" + word_count.ToString() + extension).Length < 50)
                                    {
                                        File.Delete("download/file" + word_count.ToString() + extension);
                                        throw new TimeoutException();
                                    }

                                    word_count++;
                                    counter++;
                                    links_to_source.Add(address);
                                    Application.DoEvents();
                                }
                                catch
                                {
                                    download_fails++;
                                }
                            }
                            else
                            {
                                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
                                HttpWebResponse response;
                                request.Timeout = 5000;
                                try
                                {
                                    response = (HttpWebResponse)request.GetResponse();
                                    Application.DoEvents();
                                }
                                catch
                                {
                                    download_fails++;
                                    continue;
                                }

                                string content_type = response.ContentType;
                                string file_name = "";
                                content_type = content_type.Replace("msword", "doc");
                                content_type = content_type.Replace("octet-stream", "pdf");
                                content_type = content_type.Replace("22", "pdf");
                                int start = content_type.IndexOf('/');
                                int end = content_type.IndexOf(';');
                                response.Close();

                                try
                                {
                                    if (end > 0)
                                        file_name = "download/file" + word_count.ToString() + "." + content_type.Substring(start + 1, end - start - 1);
                                    else
                                        file_name = "download/file" + word_count.ToString() + "." + content_type.Substring(start + 1);

                                    Client.DownloadFileAsync(new Uri(address), file_name);
                                    DateTime timeout = DateTime.Now;

                                    while (Client.IsBusy)
                                    {
                                        if ((DateTime.Now - timeout).Seconds > 50)
                                        {
                                            Client.CancelAsync();
                                            while (IsFileInUse(new FileInfo("download/file" + word_count.ToString() + extension)))
                                            { }
                                            File.Delete(file_name);
                                            throw new TimeoutException();
                                        }
                                    }

                                    if (new FileInfo(file_name).Length < 50)
                                    {
                                        File.Delete(file_name);
                                        throw new TimeoutException();
                                    }

                                    word_count++;
                                    counter++;
                                    links_to_source.Add(address);
                                    Application.DoEvents();
                                }
                                catch
                                {
                                    download_fails++;
                                }
                            }
                        }

                        foreach (KeyValuePair<string, bool> item in search_temp_output)
                        {
                            if (!search_output.ContainsKey(item.Key))
                                search_output.Add(item.Key, item.Value);
                        }
                        search_temp_output.Clear();
                    }

                    // pokud je zapnuto automatické porovnání, porovná stažené zdroje s dokumentem
                    if (CheckCompare.Checked)
                    {
                        IniReaderWriter iniprocessingunit = new IniReaderWriter();
                        bool finished_ok = false;
                        List<string> dl_files = new List<string>();
                        dl_files = (Directory.GetFiles("download")).ToList<string>();
                        dl_files.Sort((x, y) => ExtractNumber(x).CompareTo(ExtractNumber(y)));
                        string message1 = String.Format("(4/4) Probíhá {0} vyhledávání, stahování a porovnání zdrojů. ", search_strings.Count);
                        string message2 = String.Format("/{0} zdrojů porovnáno. Čekejte prosím.", word_count - last_downloaded);


                        iniprocessingunit.AddNewSection("Results");
                        iniprocessingunit.AddNewKey("Results", "UsedN", TrackNValue.Value.ToString());
                        iniprocessingunit.AddNewKey("Results", "SuspectNGrams", suspect_ngrams_number.ToString());
                        iniprocessingunit.AddNewKey("Results", "SourceNGrams", " ");
                        iniprocessingunit.AddNewKey("Results", "NumofPositives", " ");
                        iniprocessingunit.AddNewKey("Results", "CosSimiliarity", " ");
                        iniprocessingunit.AddNewKey("Results", "ClusterScore", " ");

                        StatusText.Text = message1 + 0 + message2;

                        // porovnat zdroje od last_downloaded do word_count
                        for (int i = last_downloaded; i < word_count; i++)
                        {
                            Application.DoEvents();
                            if (!running)
                            {
                                DisableEnableControls(true);
                                StatusText.Text = "Vyhledávání zrušeno.";
                                StatusProgressBar.Value = StatusProgressBar.Maximum;
                                return;
                            }

                            // převod na text
                            finished_ok = false;

                            switch (Path.GetExtension(dl_files[i]))
                            {
                                case ".pdf": finished_ok = OpenPDFFile(dl_files[i], false, true); break;
                                case ".TXT":
                                case ".txt": finished_ok = OpenTextFile(dl_files[i], false); break;
                                case ".html": finished_ok = OpenHTMLFile(dl_files[i], false); break;
                                case ".htm": finished_ok = OpenHTMLFile(dl_files[i], false); break;
                                case ".doc":
                                case ".docx": finished_ok = OpenDOCFile(dl_files[i], false); break;
                                default: File.AppendAllText("Error_log.txt", "Chyba: Neplatný typ souboru.\r\n"); break;
                            }

                            if (!finished_ok)
                            {
                                StatusText.Text = message1 + (i - last_downloaded) + message2;
                                continue;
                            }

                            Application.DoEvents();

                            // čištění textu
                            try
                            {
                                // volba znakové sady
                                string use_encoding = "UTF-8";

                                switch (Path.GetExtension(dl_files[i]))
                                {
                                    case ".pdf": use_encoding = "ISO-8859-2";
                                        break;
                                    case ".txt":
                                    case ".html":
                                    case ".htm":
                                        if (CheckForceEncoding.Checked && ComboEncoding.SelectedIndex != -1)
                                            use_encoding = ComboEncoding.SelectedItem.ToString();
                                        break;
                                    default: File.AppendAllText("Error_log.txt", "Chyba: Neplatný typ souboru.\r\n"); break;
                                }

                                // čištění textu
                                using (StreamReader reader = new StreamReader(String.Format("reports\\file{0}.txt", i), System.Text.Encoding.GetEncoding(use_encoding)))
                                {
                                    while (reader.Peek() != -1)
                                    {
                                        File.AppendAllText(String.Format("reports\\file{0}_clean.txt", i), CleanTextFile(reader.ReadLine()), Encoding.GetEncoding(28592));
                                        Application.DoEvents();
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                File.Delete(String.Format("reports\\file{0}_clean.txt", i));
                                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                                StatusText.Text = message1 + (i - last_downloaded) + message2;
                                continue;
                            }

                            Application.DoEvents();
                            // lematizace
                            LemmatizeFile(String.Format("reports\\file{0}_clean.txt", i), String.Format("reports\\file{0}_lemma.txt", i));

                            Application.DoEvents();
                            // vytvoření n-gramů
                            iniprocessingunit.ChangeKeyValue("Results", "SourceNGrams", (CreateNGrams(String.Format("reports\\file{0}_lemma.txt", i), String.Format("reports\\file{0}_ngram.txt", i), TrackNValue.Value, ref word_table)).ToString());

                            Application.DoEvents();
                            if (!running)
                            {
                                DisableEnableControls(true);
                                StatusText.Text = "Vyhledávání zrušeno.";
                                StatusProgressBar.Value = StatusProgressBar.Maximum;
                                return;
                            }

                            // porovnání souborů
                            if (!Compare2NGrams("Ngrams.txt", String.Format("reports\\file{0}_ngram.txt", i), ref iniprocessingunit, TrackNValue.Value, true))
                            {
                                File.Delete(String.Format("reports\\file{0}_clean.txt", i));
                                File.Delete(String.Format("reports\\file{0}_lemma.txt", i));
                                File.Delete(String.Format("reports\\file{0}_ngram.txt", i));
                                StatusText.Text = message1 + (i - last_downloaded) + message2;
                                continue;
                            }

                            // uložení výsledku
                            try
                            {
                                iniprocessingunit.RewriteIniFile(String.Format("reports\\file{0}_result.ini", i));
                            }
                            catch (Exception ex)
                            {
                                File.Delete(String.Format("reports\\file{0}_clean.txt", i));
                                File.Delete(String.Format("reports\\file{0}_lemma.txt", i));
                                File.Delete(String.Format("reports\\file{0}_ngram.txt", i));
                                File.Delete(String.Format("reports\\file{0}_result.ini", i));
                                File.Delete(String.Format("reports\\file{0}_positives.txt", i));
                                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                                StatusText.Text = message1 + (i - last_downloaded) + message2;
                                continue;
                            }

                            StatusText.Text = message1 + (i - last_downloaded) + message2;
                        }

                        // reset word_table, aby nenarůstala donekonečna
                        word_table.Clear();
                        Application.DoEvents();

                        foreach (KeyValuePair<string, int> item in word_table_backup)
                        {
                            word_table.Add(String.Copy(item.Key), item.Value);
                        }
                    }

                    StatusProgressBar.Value++;
                    Application.DoEvents();
                    if (!running)
                    {
                        DisableEnableControls(true);
                        StatusText.Text = "Vyhledávání zrušeno.";
                        return;
                    }
                }

                StatusProgressBar.Value = StatusProgressBar.Maximum;
                Application.DoEvents();

                // zobrazení výsledku
                if (CheckCompare.Checked)
                {
                    IniReaderWriter iniprocessingunit = new IniReaderWriter();
                    string[] results = Directory.GetFiles("reports", "*.ini");
                    int alert = 0, count_alert = 0, count_high_alert = 0;

                    try
                    {
                        for (int i = 0; i < results.Length; i++)
                        {
                            iniprocessingunit.ReadIniFile(results[i]);
                            alert = 0;

                            if (CheckCosSim.Checked)
                            {
                                if ((NumericCosSimLimit.Value / 100) <= decimal.Parse(iniprocessingunit.GetKeyValue("Results", "CosSimiliarity")))
                                    alert++;
                            }
                            if (CheckClusterScore.Checked)
                            {
                                if ((Convert.ToInt32(ComboClusterScoreLimit.SelectedItem) <= int.Parse(iniprocessingunit.GetKeyValue("Results", "ClusterScore"))))
                                    alert++;
                            }

                            switch (alert)
                            {
                                case 1: count_alert++; break;
                                case 2: count_high_alert++; break;
                            }

                            iniprocessingunit.FlushIniData();
                        }
                    }
                    catch (Exception ex)
                    {
                        System.Media.SystemSounds.Hand.Play();
                        File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                        if (files_to_do.Length == 1)
                            StatusText.Text = "Chyba: Nelze přečíst výsledky předchozích porovnání.";
                    }

                    if (download_fails == 0)
                        StatusText.Text = String.Format("Vyhledávání dokončeno, {0} zdrojů nalezeno a staženo. {1} zdrojů úspěšně porovnáno - {2} podezřelých, {3} velmi podezřelých.", word_count, results.Length, count_alert, count_high_alert);
                    else
                        StatusText.Text = String.Format("{0} zdrojů staženo. {1} zdrojů nebylo možné stáhnout. {2} zdrojů úspěšně porovnáno - {3} podezřelých, {4} velmi podezřelých.", word_count, download_fails, results.Length, count_alert, count_high_alert);
                }
                else
                {
                    if (download_fails == 0)
                        StatusText.Text = String.Format("Vyhledávání dokončeno, {0} zdrojů nalezeno a staženo.", word_count);
                    else
                        StatusText.Text = String.Format("Vyhledávání dokončeno, {0} zdrojů nalezeno a staženo. {1} zdrojů nebylo možné stáhnout.", word_count, download_fails);
                }

                LabelSuspectWordsTotal.Text = num_of_words_suspect_total.ToString();


                DateTime end_time = DateTime.Now;

                // výsledky
                SearchResultSummary(Path.GetFileName(file_path), end_time - begin_time, download_fails, links_to_source);

                // zobrazení stránek s výsledkem vyhledávání
                if (files_to_do.Length == 1 && CheckShowSearch.Checked)
                {
                    BrowserForm.SetUrlsToShow(search_strings);
                    BrowserForm.Show();
                }
            }

            UpdateSources();
            DisableEnableControls(true);
        }

        // Pokusí se otevřít Original.txt a předpokládá že všecny existující zpracované soubory patří k němu
        // je třeba dokončit, přidat podmínky do ostatních funkcí a tak
        private void ButtonOpenLastClick(object sender, EventArgs e)
        {
            if (!File.Exists("Original.txt"))
            {
                StatusText.Text = "Dokument se nepodařilo obnovit. Záznam dokumentu neexistuje.";
                return;
            }

            try
            {
                FileInfo info = new FileInfo("Original.txt");

                if (info.Length == 0)
                {
                    StatusText.Text = "Dokument se nepodařilo obnovit. Záznam dokumentu neobsahuje data.";
                    return;
                }
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Dokument se nepodařilo obnovit.";
                return;
            }

            GroupLeft.Text = "Podezřelý dokument: \"" + Path.GetFileName(last_opened) + "\"";
            TextBoxSuspect.Text = File.ReadAllText("Original.txt", System.Text.Encoding.GetEncoding(28592));

            LabelSuspectWordsTotal.Text = num_of_words_suspect_total.ToString();
            LabelSuspectUniques.Text = num_of_uniques_suspect.ToString();
            UpdateSources();
            SourceSelectedUpdate();

            StatusText.Text = "Obnovení dokumentu dokončeno.";
        }

        // zjistí, který soubor je třeba otevřít a zavolá potřebnou metodu
        private void ButtonViewFileClick(object sender, EventArgs e)
        {
            string file = "";
            int i = Convert.ToInt32(NumSourceSelect.Value);

            StatusText.Text = "Otevírám zdrojový dokument. Čekejte prosím.";
            StatusProgressBar.Value = 0;
            StatusProgressBar.Maximum = 3;
            Application.DoEvents();

            file = "file" + i.ToString();

            List<string> files = new List<string>();
            files = (Directory.GetFiles("download")).ToList<string>();
            files.Sort((x, y) => ExtractNumber(x).CompareTo(ExtractNumber(y)));

            bool finished_ok = false;

            switch (Path.GetExtension(files[i]))
            {
                case ".pdf": finished_ok = OpenPDFFile(files[i], true, false);
                    break;
                case ".TXT":
                case ".txt": finished_ok = OpenTextFile(files[i], true);
                    break;
                case ".html": finished_ok = OpenHTMLFile(files[i], true);
                    break;
                case ".htm": finished_ok = OpenHTMLFile(files[i], true);
                    break;
                case ".doc":
                case ".docx": finished_ok = OpenDOCFile(files[i], true);
                    break;
                default: StatusText.Text = "Chyba: Neplatný typ souboru."; break;
            }

            if (!finished_ok)
            {
                return;
            }

            StatusProgressBar.Value = 1;
            Application.DoEvents();

            if (File.Exists(@"reports/" + file + "_result.ini"))
                UpdateResults(@"reports/" + file + "_result.ini");

            TextBoxSource.SelectAll();
            TextBoxSource.SelectionBackColor = SystemColors.Control;
            TextBoxSuspect.SelectAll();
            TextBoxSuspect.SelectionBackColor = SystemColors.Control;

            StatusProgressBar.Value = 2;
            Application.DoEvents();

            if (File.Exists(String.Format("reports\\{0}_positives.txt", file)))
                MarkPositivesinText(Int32.Parse(Regex.Match(file, @"\d+").Value));

            StatusProgressBar.Value = StatusProgressBar.Maximum;
            StatusText.Text = "Otevření zdrojového dokumentu dokončeno.";
            Application.DoEvents();
        }

        // porovná zdroj s podezřelým dokumentem
        // Vytvoří potřebné textové soubory v results složce, včetně výsledku porovnání a zobrazí výsledek uživateli
        private void ButtonFileCompClick(object sender, EventArgs e)
        {
            StatusText.Text = "(1/4) Probíhá čištění textu. Čekejte prosím.";
            StatusProgressBar.Value = 0;
            StatusProgressBar.Maximum = 1;
            Application.DoEvents();

            IniReaderWriter iniprocessingunit = new IniReaderWriter();
            int file_num = Convert.ToInt32(NumSourceSelect.Value);
            string file = "file" + file_num.ToString();
            List<string> files = new List<string>();
            files = (Directory.GetFiles("download")).ToList<string>();
            files.Sort((x, y) => ExtractNumber(x).CompareTo(ExtractNumber(y)));

            iniprocessingunit.AddNewSection("Results");
            iniprocessingunit.AddNewKey("Results", "UsedN", TrackNValue.Value.ToString());

            // převod na text pokud ještě nebylo provedeno
            if (!File.Exists(@"reports/" + file + ".txt"))
            {
                bool finished_ok = false;

                switch (Path.GetExtension(files[file_num]))
                {
                    case ".pdf": finished_ok = OpenPDFFile(files[file_num], true, false);
                        break;
                    case ".TXT":
                    case ".txt": finished_ok = OpenTextFile(files[file_num], true);
                        break;
                    case ".html": finished_ok = OpenHTMLFile(files[file_num], true);
                        break;
                    case ".htm": finished_ok = OpenHTMLFile(files[file_num], true);
                        break;
                    case ".doc":
                    case ".docx": finished_ok = OpenDOCFile(files[file_num], true);
                        break;
                    default: StatusText.Text = "Chyba: Neplatný typ souboru."; break;
                }

                if (!finished_ok)
                {
                    return;
                }
            }

            File.Delete(@"reports/" + file + "_clean.txt");
            File.Delete(@"reports/" + file + "_lemma.txt");
            File.Delete(@"reports/" + file + "_ngram.txt");
            File.Delete(@"reports/" + file + "_positives.txt");
            File.Delete(@"reports/" + file + "_result.ini");
            File.Delete("Positives_" + file + ".txt");
            File.Delete("Ngrams.txt");

            // čištění textu
            try
            {
                // volba znakové sady
                string use_encoding = "UTF-8";

                switch (Path.GetExtension(files[file_num]))
                {
                    case ".pdf": use_encoding = "ISO-8859-2";
                        break;
                    case ".txt":
                    case ".html":
                    case ".htm":
                        if (CheckForceEncoding.Checked && ComboEncoding.SelectedIndex != -1)
                            use_encoding = ComboEncoding.SelectedItem.ToString();
                        break;
                    default: StatusText.Text = "Chyba: Neplatný typ souboru."; break;
                }

                // čištění textu
                using (StreamReader reader = new StreamReader(@"reports\" + file + ".txt", System.Text.Encoding.GetEncoding(use_encoding)))
                {
                    while (reader.Peek() != -1)
                    {
                        File.AppendAllText(@"reports/" + file + "_clean.txt", CleanTextFile(reader.ReadLine()), Encoding.GetEncoding(28592));
                    }
                }

                TextBoxSource.Text = File.ReadAllText(@"reports\" + file + ".txt", System.Text.Encoding.GetEncoding(use_encoding));
                GroupRight.Text = "Nalezený zdroj: \"" + file + ".txt" + "\"";
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Chyba: Nastala chyba při čištění zdrojového souboru.";
                File.Delete(@"reports/" + file + "_clean.txt");
                return;
            }

            StatusText.Text = "(2/4) Probíhá lematizace textu. Čekejte prosím.";
            Application.DoEvents();

            // lematizace textu
            LemmatizeFile(@"reports/" + file + "_clean.txt", @"reports/" + file + "_lemma.txt");

            StatusText.Text = "(3/4) Probíhá vytváření n-gramů. Čekejte prosím.";
            StatusProgressBar.Value = 0;
            StatusProgressBar.Maximum = 2;
            Application.DoEvents();

            // vytvoření n-gramů
            Dictionary<string, int> word_table = new Dictionary<string, int>();
            
            if(File.Exists("Processed.txt"))
                iniprocessingunit.AddNewKey("Results", "SuspectNGrams", (CreateNGrams("Processed.txt", "Ngrams.txt", TrackNValue.Value, ref word_table)).ToString());
            else
                iniprocessingunit.AddNewKey("Results", "SuspectNGrams", (CreateNGrams("Cleaned.txt", "Ngrams.txt", TrackNValue.Value, ref word_table)).ToString());
            StatusProgressBar.Value = 1;
            Application.DoEvents();
            iniprocessingunit.AddNewKey("Results", "SourceNGrams", (CreateNGrams(@"reports/" + file + "_lemma.txt", @"reports/" + file + "_ngram.txt", TrackNValue.Value, ref word_table)).ToString());

            StatusText.Text = "(4/4) Probíhá porovnání dokumentů. Čekejte prosím.";
            StatusProgressBar.Value = 0;
            Application.DoEvents();

            iniprocessingunit.AddNewKey("Results", "NumofPositives", " ");
            iniprocessingunit.AddNewKey("Results", "CosSimiliarity", " ");
            iniprocessingunit.AddNewKey("Results", "ClusterScore", " ");

            // porovnání dokumentů
            if (Compare2NGrams("Ngrams.txt", @"reports/" + file + "_ngram.txt", ref iniprocessingunit, TrackNValue.Value, false))
                StatusText.Text = "Porovnání dokumentů dokončeno.";
            else
            {
                File.Delete(@"reports/" + file + "_clean.txt");
                File.Delete(@"reports/" + file + "_lemma.txt");
                File.Delete(@"reports/" + file + "_ngram.txt");
                return;
            }

            try
            {
                iniprocessingunit.RewriteIniFile(@"reports/" + file + "_result.ini");

                UpdateResults(@"reports/" + file + "_result.ini");
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Chyba: Nepodařilo se uložit výsledek porovnání dokumentů.";
            }

            TextBoxSource.SelectAll();
            TextBoxSource.SelectionBackColor = SystemColors.Control;
            TextBoxSuspect.SelectAll();
            TextBoxSuspect.SelectionBackColor = SystemColors.Control;

            NumSourceSelect.Value = NumSourceSelect.Value;
            Application.DoEvents();

            SourceSelectedUpdate();

            MarkPositivesinText(Int32.Parse(Regex.Match(file, @"\d+").Value));
        }

        // uvede odpovídající nastavení do doporučené výchozí hodnoty
        private void ButtonResetClick(object sender, EventArgs e)
        {
            string button_name = ((Button)sender).Name;

            switch (button_name)
            {
                case "ButtonSystemReset":
                    CheckFilterOnOff.Checked = true;
                    RadioAutoFilter.Checked = true;
                    CheckStartFilter.Checked = false;
                    CheckEndFilter.Checked = false;
                    CheckCompare.Checked = true;
                    CheckShowSearch.Checked = false;
                    break;
                case "ButtonSettingsReset":
                    CheckForceEncoding.Checked = false;
                    NumericFontSize.Value = 8;
                    TrackNValue.Value = 3;
                    ComboFontStyle.SelectedIndex = 1;
                    ComboClusterScoreLimit.SelectedIndex = 4;
                    NumericCosSimLimit.Value = 4;
                    CheckCosSim.Checked = true;
                    CheckClusterScore.Checked = true;
                    break;
                case "ButtonSearchReset":
                    TrackSearchWords.Value = 10;
                    TrackDownloadNum.Value = 3;
                    TrackJumpWords.Value = 3;
                    CheckLemmatize.Checked = true;
                    CheckManualInput.Checked = false;
                    CheckSearchKeyWords.Checked = false;
                    break;
            }
        }

        // porovná všechny soubory v download s dokumentem
        private void ButtonCompareAllClick(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(TextBoxSuspect.Text))
            {
                System.Media.SystemSounds.Hand.Play();
                StatusText.Text = "Chyba: Není otevřen žádný dokument.";
                return;
            }

            File.AppendAllText("Error_log.txt", "-- Porovnání všech zdrojů --\r\n");

            List<string> files = new List<string>();
            files = (Directory.GetFiles("download")).ToList<string>();

            if (files.Count == 0)
            {
                System.Media.SystemSounds.Hand.Play();
                StatusText.Text = "Chyba: Neexistují zdroje, se kterými lze dokument porovnat.";
                return;
            }

            files.Sort((x, y) => ExtractNumber(x).CompareTo(ExtractNumber(y)));

            // inicializace
            DisableEnableControls(false);

            StatusText.Text = "Probíhá vytváření n-gramů z dokumentu. Čekejte prosím.";
            StatusProgressBar.Value = 0;
            StatusProgressBar.Maximum = 1;
            Application.DoEvents();

            File.Delete("Ngrams.txt");
            string[] files_to_delete = Directory.GetFiles("reports");
            foreach (string file in files_to_delete)
            {
                File.Delete(file);
            }

            Application.DoEvents();

            // vytvoření n-gramů z dokumentu
            Dictionary<string, int> word_table = new Dictionary<string, int>();
            Dictionary<string, int> word_table_backup = new Dictionary<string, int>();
            int suspect_ngrams_number = 0;

            suspect_ngrams_number = CreateNGrams("Processed.txt", "Ngrams.txt", TrackNValue.Value, ref word_table);
            Application.DoEvents();

            // uložení kopie n-gramů
            foreach (KeyValuePair<string, int> item in word_table)
            {
                word_table_backup.Add(String.Copy(item.Key), item.Value);
            }
            Application.DoEvents();

            // inicializace ini souboru
            IniReaderWriter iniprocessingunit = new IniReaderWriter();
            bool finished_ok = false;

            iniprocessingunit.AddNewSection("Results");
            iniprocessingunit.AddNewKey("Results", "UsedN", TrackNValue.Value.ToString());
            iniprocessingunit.AddNewKey("Results", "SuspectNGrams", suspect_ngrams_number.ToString());
            iniprocessingunit.AddNewKey("Results", "SourceNGrams", " ");
            iniprocessingunit.AddNewKey("Results", "NumofPositives", " ");
            iniprocessingunit.AddNewKey("Results", "CosSimiliarity", " ");
            iniprocessingunit.AddNewKey("Results", "ClusterScore", " ");

            // hlavní blok
            StatusText.Text = String.Format("Probíhá čištění, zpracování a porovnání {0} zdrojů s dokumentem. Čekejte prosím.", files.Count);
            StatusProgressBar.Value = 0;
            StatusProgressBar.Maximum = files.Count;
            Application.DoEvents();

            for (int i = 0; i < files.Count; i++)
            {
                Application.DoEvents();
                if (!running)
                {
                    DisableEnableControls(true);
                    StatusText.Text = "Porovnávání zrušeno.";
                    return;
                }

                if (i > 0 && (i % 10) == 0)
                {
                    // reset word_table, aby nenarůstala donekonečna
                    word_table.Clear();

                    foreach (KeyValuePair<string, int> item in word_table_backup)
                    {
                        word_table.Add(String.Copy(item.Key), item.Value);
                    }
                }
                Application.DoEvents();

                // převod na text
                finished_ok = false;

                switch (Path.GetExtension(files[i]))
                {
                    case ".pdf": finished_ok = OpenPDFFile(files[i], false, true); break;
                    case ".TXT":
                    case ".txt": finished_ok = OpenTextFile(files[i], false); break;
                    case ".html": finished_ok = OpenHTMLFile(files[i], false); break;
                    case ".htm": finished_ok = OpenHTMLFile(files[i], false); break;
                    case ".doc":
                    case ".docx": finished_ok = OpenDOCFile(files[i], false); break;
                    default: File.AppendAllText("Error_log.txt", "Chyba: Neplatný typ souboru.\r\n"); break;
                }

                if (!finished_ok)
                {
                    continue;
                }

                Application.DoEvents();

                // čištění textu
                try
                {
                    // volba znakové sady
                    string use_encoding = "UTF-8";

                    switch (Path.GetExtension(files[i]))
                    {
                        case ".pdf": use_encoding = "ISO-8859-2";
                            break;
                        case ".txt":
                        case ".html":
                        case ".htm":
                            if (CheckForceEncoding.Checked && ComboEncoding.SelectedIndex != -1)
                                use_encoding = ComboEncoding.SelectedItem.ToString();
                            break;
                        default: File.AppendAllText("Error_log.txt", "Chyba: Neplatný typ souboru.\r\n"); break;
                    }
                    Application.DoEvents();

                    // čištění textu
                    using (StreamReader reader = new StreamReader(String.Format("reports\\file{0}.txt", i), System.Text.Encoding.GetEncoding(use_encoding)))
                    {
                        while (reader.Peek() != -1)
                        {
                            File.AppendAllText(String.Format("reports\\file{0}_clean.txt", i), CleanTextFile(reader.ReadLine()), Encoding.GetEncoding(28592));
                        }
                    }
                }
                catch (Exception ex)
                {
                    File.Delete(String.Format("reports\\file{0}_clean.txt", i));
                    File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                    continue;
                }
                Application.DoEvents();

                // lematizace
                LemmatizeFile(String.Format("reports\\file{0}_clean.txt", i), String.Format("reports\\file{0}_lemma.txt", i));
                Application.DoEvents();

                // vytvoření n-gramů
                iniprocessingunit.ChangeKeyValue("Results", "SourceNGrams", (CreateNGrams(String.Format("reports\\file{0}_lemma.txt", i), String.Format("reports\\file{0}_ngram.txt", i), TrackNValue.Value, ref word_table)).ToString());

                Application.DoEvents();
                if (!running)
                {
                    DisableEnableControls(true);
                    StatusText.Text = "Porovnávání zrušeno.";
                    return;
                }

                // porovnání souborů
                if (!Compare2NGrams("Ngrams.txt", String.Format("reports\\file{0}_ngram.txt", i), ref iniprocessingunit, TrackNValue.Value, true))
                {
                    File.Delete(String.Format("reports\\file{0}_clean.txt", i));
                    File.Delete(String.Format("reports\\file{0}_lemma.txt", i));
                    File.Delete(String.Format("reports\\file{0}_ngram.txt", i));
                    continue;
                }

                Application.DoEvents();

                // uložení výsledku
                try
                {
                    iniprocessingunit.RewriteIniFile(String.Format("reports\\file{0}_result.ini", i));
                }
                catch (Exception ex)
                {
                    File.Delete(String.Format("reports\\file{0}_clean.txt", i));
                    File.Delete(String.Format("reports\\file{0}_lemma.txt", i));
                    File.Delete(String.Format("reports\\file{0}_ngram.txt", i));
                    File.Delete(String.Format("reports\\file{0}_result.ini", i));
                    File.Delete(String.Format("reports\\file{0}_positives.txt", i));
                    File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                    continue;
                }

                StatusProgressBar.Value++;
            }


            // ukončení
            StatusProgressBar.Value = StatusProgressBar.Maximum;
            Application.DoEvents();

            iniprocessingunit.FlushIniData();
            string[] results = Directory.GetFiles("reports", "*.ini");
            int alert = 0, count_alert = 0, count_high_alert = 0;

            try
            {
                for (int i = 0; i < results.Length; i++)
                {
                    iniprocessingunit.ReadIniFile(results[i]);
                    alert = 0;

                    if (CheckCosSim.Checked)
                    {
                        if ((NumericCosSimLimit.Value / 100) <= decimal.Parse(iniprocessingunit.GetKeyValue("Results", "CosSimiliarity")))
                            alert++;
                    }
                    if (CheckClusterScore.Checked)
                    {
                        if ((Convert.ToInt32(ComboClusterScoreLimit.SelectedItem) <= int.Parse(iniprocessingunit.GetKeyValue("Results", "ClusterScore"))))
                            alert++;
                    }

                    switch (alert)
                    {
                        case 1: count_alert++; break;
                        case 2: count_high_alert++; break;
                    }

                    iniprocessingunit.FlushIniData();
                }
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Chyba: Nelze přečíst výsledky předchozích porovnání.";
            }

            StatusText.Text = String.Format("Porovnání {0} zdrojů dokončeno. {1} zdrojů úspěšně porovnáno - {2} podezřelých, {3} velmi podezřelých.", files.Count, results.Length, count_alert, count_high_alert);

            DisableEnableControls(true);

            UpdateSources();
        }

        // obnovuje informace při změně zdroje
        private void SourceSelectedChanged(object sender, EventArgs e)
        {
            SourceSelectedUpdate();
        }

        // zabrání přepnutí mezi záložkami při běhu
        private void MainControlTabChanged(object sender, EventArgs e)
        {
            if (running)
                MainControl.SelectedIndex = 0;

            if (!String.IsNullOrEmpty(TextBoxSuspect.Text) && MainControl.SelectedIndex == 1)
                UpdateSources();
        }

        // zastaví probíhající proces
        private void ButtonStopClick(object sender, EventArgs e)
        {
            running = false;
        }

        //-------------------------- pomocné metody -----------------------


        //Převede PDF dokument na text
        // parametry - cesta pdf, cesta txt (přepisuje), filtrovat ano/ne, filtr auto(1)/manual(0), X prvních stran, Y posledních stran
        // cesty relativně, vrací true pokud proběhne bez chyb
        private bool ConvertPDFtoText(string input_path, string output_path, bool filter_file, bool filter_auto, uint filter_start, uint filter_end, bool suspect, bool silent)
        {
            if (!silent)
            {
                StatusProgressBar.Value = 0;
                Application.DoEvents();
            }

            // Zjištění informací o souboru
            Process pdf_info = new Process();
            int error = 99;

            pdf_info.StartInfo.UseShellExecute = false;
            pdf_info.StartInfo.RedirectStandardOutput = true;
            pdf_info.StartInfo.FileName = "pdfinfo.exe";
            pdf_info.StartInfo.Arguments = "-cfg config.xpdfrc -enc Latin2 " + input_path;

            pdf_info.Start();
            string info_output = pdf_info.StandardOutput.ReadToEnd();
            if (!pdf_info.WaitForExit(10000))
                pdf_info.Kill();
            else
                error = pdf_info.ExitCode;   //exit code: 0 nic, 1 error otevření pdf, 2 error otevření txt, 3 error neoprávněn přistoupit k pdf, 99 jiné

            if (error > 0)
            {
                System.Media.SystemSounds.Hand.Play();
                if (!silent)
                {
                    switch (error)
                    {
                        case 1:
                            StatusText.Text = "Chyba (pdfinfo.exe): Otevření vstupního PDF souboru selhalo.";
                            break;
                        case 2:
                            StatusText.Text = "Chyba (pdfinfo.exe): Otevření výstupního TXT souboru selhalo.";
                            break;
                        case 3:
                            StatusText.Text = "Chyba (pdfinfo.exe): Nedostatečné oprávnění k otevření vstupního PDF souboru.";
                            break;
                        default:
                            StatusText.Text = "Chyba (pdfinfo.exe): Nastala chyba při čtení informací z PDF souboru.";
                            break;
                    }
                }
                return false;
            }

            //zjištění počtu stran
            int index = info_output.IndexOf("Pages:");
            char temp = 'a';
            string result = "";
            while (temp != '\r')
            {
                temp = info_output[index];
                if (Char.IsDigit(temp))
                    result += temp;
                index++;
            }

            int number_of_pages = Convert.ToInt32(result);

            if (suspect)
                num_of_pages_suspect = number_of_pages;

            // Dále samotný převod
            Process pdf_to_text = new Process();

            pdf_to_text.StartInfo.UseShellExecute = false;
            pdf_to_text.StartInfo.RedirectStandardError = true;
            pdf_to_text.StartInfo.FileName = "pdftotext.exe";

            pdf_to_text.StartInfo.Arguments = "-cfg config.xpdfrc -enc Latin2";

            //Filtrace X prvních a Y posledních stran
            if (filter_file && !filter_auto)
            {
                pdf_to_text.StartInfo.Arguments += String.Format(" -f {0} -l {1}", 1 + filter_start, number_of_pages - filter_end);
                number_of_pages = number_of_pages - Convert.ToInt32(filter_start) - Convert.ToInt32(filter_end);
            }

            // cesty k souborům
            pdf_to_text.StartInfo.Arguments += " " + input_path;
            if (filter_file && filter_auto)
                pdf_to_text.StartInfo.Arguments += " Temporary.txt";
            else
                pdf_to_text.StartInfo.Arguments += " " + output_path;

            //převod na text
            error = 99;
            pdf_to_text.Start();
            if (!pdf_to_text.WaitForExit(40000))
                pdf_to_text.Kill();
            else
                error = pdf_to_text.ExitCode;   //exit code: 0 nic, 1 error otevření pdf, 2 error otevření txt, 3 error neoprávněn přistoupit k pdf, 99 jiné

            if (error > 0)
            {
                System.Media.SystemSounds.Hand.Play();
                if (!silent)
                {
                    switch (error)
                    {
                        case 1:
                            StatusText.Text = "Chyba (pdftotext.exe): Otevření vstupního PDF souboru selhalo.";
                            break;
                        case 2:
                            StatusText.Text = "Chyba (pdftotext.exe): Otevření výstupního TXT souboru selhalo.";
                            break;
                        case 3:
                            StatusText.Text = "Chyba (pdftotext.exe): Nedostatečné oprávnění k otevření vstupního PDF souboru.";
                            break;
                        default:
                            StatusText.Text = "Chyba (pdftotext.exe): Nastala chyba při převodu PDF souboru na TXT soubor.";
                            File.Delete(output_path);
                            break;
                    }
                }
                return false;
            }

            // automatická filtrace
            if (filter_file && filter_auto)
            {
                //inicializace progress baru
                if (!silent)
                {
                    StatusProgressBar.Value = 0;
                    StatusProgressBar.Maximum = number_of_pages;
                    Application.DoEvents();
                }

                //samotná filtrace
                try
                {
                    StreamReader reader = new StreamReader("Temporary.txt", System.Text.Encoding.GetEncoding(28592));
                    string page = String.Empty;
                    bool trim_allowed = true;
                    int page_number = 0;
                    int pages_removed = 0;

                    while (LoadPage(ref page, ref reader))
                    {
                        page_number++;
                        if (!silent)
                        {
                            StatusProgressBar.Value++;
                            Application.DoEvents();
                        }

                        // zapne ořezání konce dokumentu
                        if (trim_allowed == false && page_number >= System.Convert.ToInt32(number_of_pages * 0.85))
                            trim_allowed = true;

                        if (trim_allowed)
                        {
                            if (CheckForRemoval(page))
                            {
                                pages_removed++;
                                continue;                   // přeskočí uložení strany do text souboru
                            }
                            else
                                trim_allowed = false;       //vypne ořezání, aby střed dokumentu zůstal nezměněn
                        }

                        // uloží stranu do txt souboru
                        File.AppendAllText(@"Original.txt", page, System.Text.Encoding.GetEncoding(28592));
                    }

                    if (suspect)
                        num_of_pages_suspect = num_of_pages_suspect - pages_removed;
                    reader.Dispose();
                }
                catch (Exception ex)
                {
                    System.Media.SystemSounds.Hand.Play();
                    File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                    if (!silent)
                        StatusText.Text = "Chyba: Nastala chyba při automatické filtraci souboru.";
                    File.Delete("Temporary.txt");
                    return false;
                }
                File.Delete("Temporary.txt");
            }

            if (!silent)
            {
                StatusProgressBar.Value = StatusProgressBar.Maximum;
                Application.DoEvents();
            }
            return true;
        }

        // vrátí string, který obsahuje text vstupního stringu ve formátu jednotlivých slov oddělených mezerami bez rozlišení velkých a malých písmen
        // Jsou odstraněny nadbytečné informace jako číslování a častá slova bez významu (spojky, předložky)
        private string CleanTextFile(string text_to_clean)
        {
            string result = "";
            string temp = "";

            for (int i = 0; i < text_to_clean.Length; i++)
            {
                while (i < text_to_clean.Length && (Char.IsPunctuation(text_to_clean[i]) || Char.IsWhiteSpace(text_to_clean[i]) || text_to_clean[i] == '\r' || text_to_clean[i] == '\n' || text_to_clean[i] == '\f'))
                {
                    i++;
                }
                while (i < text_to_clean.Length && !Char.IsPunctuation(text_to_clean[i]) && !Char.IsWhiteSpace(text_to_clean[i]) && text_to_clean[i] != '\r' && text_to_clean[i] != '\n' && text_to_clean[i] != '\f')
                {
                    temp += Char.ToLower(text_to_clean[i]);
                    i++;
                }

                // zkontroluje jestli není stopslovo a přidá slovo do výsledku
                if (Regex.IsMatch(temp, @"\D") && String.Compare(temp, "") != 0)
                {
                    if (!stopwords.ContainsKey(temp))
                    {
                        result += temp + " ";
                        num_of_words_suspect++;
                    }
                }
                num_of_words_suspect_total++;
                temp = "";
            }

            return result;
        }

        // spustí lemmatizaci textového souboru, vrátí true pokud proběhne bez chyb
        private bool LemmatizeFile(string input_path, string output_path)
        {
            Process lemmatize_file = new Process();

            lemmatize_file.StartInfo.UseShellExecute = false;
            lemmatize_file.StartInfo.FileName = "Lemmatizer.exe";
            lemmatize_file.StartInfo.Arguments = input_path + " " + output_path;

            lemmatize_file.Start();
            Application.DoEvents();
            lemmatize_file.WaitForExit();
            int error = lemmatize_file.ExitCode;

            if (error > 0)
            {
                System.Media.SystemSounds.Hand.Play();
                if (error == 1)
                    StatusText.Text = "Chyba (Lemmatizer.exe): Neplatný počet argumentů.";
                else
                    StatusText.Text = "Chyba (Lemmatizer.exe): Chyba při lemmatizaci vstupního souboru.";
                return false;
            }

            return true;
        }

        //přečte jednu stranu z textového souboru, vrací false když narazí na konec souboru
        private bool LoadPage(ref String a_text, ref StreamReader areader)
        {
            string temp = String.Empty;
            a_text = temp;

            while (areader.Peek() != '\f')
            {
                temp = areader.ReadLine();

                if (temp == null)
                    return (false);

                a_text += temp + "\r\n";
            }

            a_text += Convert.ToChar(areader.Read());
            return (true);
        }

        // doplní do slovníku unikátní slova, včetně pozic na kterých se vyskytují
        private bool LoadUniqueWords(string file_path, ref Dictionary<string, uint> uniques_list)
        {
            string word = "";

            try
            {
                using (StreamReader reader = new StreamReader(file_path, Encoding.GetEncoding(28592)))
                {
                    do
                    {
                        while (reader.Peek() != ' ')
                        {
                            word += Convert.ToChar(reader.Read());
                        }
                        reader.Read();

                        // pokud je obsažen, přidá pozici, jinak přidá nový pár string,list
                        if (uniques_list.ContainsKey(word))
                        {
                            uniques_list[word]++;
                        }
                        else
                        {
                            uniques_list.Add(word, 1);
                        }

                        word = "";
                    } while (reader.Peek() != -1);
                }
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Chyba: Nastala chyba při vytváření seznamu unikátních slov.";
                return false;
            }

            return true;
        }

        // vytvoří seznam stop slov ze souboru
        private void CreateStopWordsList()
        {
            string word = "";

            try
            {
                using (StreamReader reader = new StreamReader("PlagSearcherPro_stopwords.txt", System.Text.Encoding.UTF8))
                {
                    do
                    {
                        while (reader.Peek() != ',')
                        {
                            word += Convert.ToChar(reader.Read());
                        }
                        reader.Read();

                        stopwords.Add(word, true);

                        word = "";
                    } while (reader.Peek() != -1);
                }
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Chyba: Nastala chyba při vytváření seznamu stop slov.";
            }
        }

        // hledá řetězce k odstranění na stránce, pokud je najde vrátí true
        private bool CheckForRemoval(String aString)
        {
            string[] lines_to_remove = { "vysoké učení technické v brně", "bakalářská práce", "pokyny pro vypracování", "poděkování", "abstrakt", "abstract", "obsah", "seznam obrázků", "seznam tabulek", "seznam symbolů a zkratek", "seznam příloh", "prohlášení", "bibliografická citace", "literatura", "ttp://", "......................................................" };
            
            for (int k = 0; k < lines_to_remove.Length; k++)
            {
                if (aString.IndexOf(lines_to_remove[k], System.StringComparison.CurrentCultureIgnoreCase) >= 0)
                {
                    if (aString.IndexOf(" " + lines_to_remove[k], System.StringComparison.CurrentCultureIgnoreCase) < 0 || lines_to_remove[k].Length > 30)
                        return (true);
                }
            }
            return (false);
        }

        // vybere z textu stránky výsledku vyhledávání odkazy na jednotlivé výsledky
        private List<string> GetUrls(string text)
        {
            List<string> result = new List<string>();
            string[] url_ignore = { "plus.google", "maps.google", "play.google", "google.cz/search", "google.com/search", "google.cz/web", 
                                      "google.com/web", "www.youtube", "news.google", "mail.google", "drive.google", "google.cz/intl", 
                                      "google.com/calendar", "translate.google", "blogger.com/?tab", "docs.google.com/document/?usp", 
                                  "google.cz/preferences", "schema.org", "apis.google", "google.cz/history", "webcache", "scholar.google" };
            string temp = "";
            int state = -1;
            bool ignore_extracted = false;

            foreach (char c in text)
            {
                switch (state)
                {
                    case -1:
                        if (c == '=')
                            state = 0; break;
                    case 0:
                        if (c == '"')
                            state = 1;
                        else
                            state = -1; break;
                    case 1:
                        if (c == 'h')
                            state = 2;
                        else
                            state = -1; break;
                    case 2:
                        if (c == 't')
                            state = 3;
                        else
                            state = -1; break;
                    case 3:
                        if (c == 't')
                            state = 4;
                        else
                            state = -1; break;
                    case 4:
                        if (c == 'p')
                            state = 5;
                        else
                            state = -1; break;
                    case 5:
                        if (c == 's' || c == ':')
                        {
                            temp += c;
                            state = 6;
                        }
                        else
                        {
                            state = -1;
                        } break;
                    case 6:
                        if ((c == ':' && String.Compare(temp, "s") == 0) || (c == '/' && String.Compare(temp, ":") == 0))
                        {
                            temp += c;
                            state = 7;
                        }
                        else
                        {
                            state = -1; temp = "";
                        } break;
                    case 7:
                        if ((c == '/' && String.Compare(temp, "s:") == 0) || (c == '/' && String.Compare(temp, ":/") == 0))
                        {
                            temp += c;
                            state = 8;
                        }
                        else
                        {
                            state = -1; temp = "";
                        } Application.DoEvents(); break;
                    case 8:
                        if ((c == '/' && String.Compare(temp, "s:/") == 0) || String.Compare(temp, "://") == 0)
                        {
                            temp += c;
                            state = 9;
                        }
                        else
                        {
                            state = -1; temp = "";
                        } break;
                    case 9:
                        if (c == '"')
                        {
                            for (int i = 0; i < url_ignore.Length; i++)
                            {
                                if (temp.IndexOf(url_ignore[i]) != -1)
                                {
                                    ignore_extracted = true;
                                    break;
                                }
                            }

                            if (!ignore_extracted)
                                result.Add("http" + temp);
                            else
                                ignore_extracted = false;

                            temp = "";
                            state = -1;
                        }
                        else
                            temp += c;
                        break;
                }
            }

            return (result);
        }

        // zobrazí zdrojové soubory typu PDF
        private bool OpenPDFFile(string path, bool open_it, bool silent)
        {
            // pokud již byl vytvořen text, přečte ho
            if (File.Exists(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt"))
            {
                if (open_it)
                {
                    GroupRight.Text = "Nalezený zdroj: \"" + Path.GetFileName(path) + "\"";
                    TextBoxSource.Text = File.ReadAllText(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt", System.Text.Encoding.GetEncoding(28592));
                }
                return true;
            }

            bool finished_ok = ConvertPDFtoText(path, @"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt", false, false, 0, 0, false, silent);

            if (finished_ok)
            {
                // zobrazení souboru
                if (open_it)
                {
                    GroupRight.Text = "Nalezený zdroj: \"" + Path.GetFileName(path) + "\"";
                    TextBoxSource.Text = File.ReadAllText(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt", System.Text.Encoding.GetEncoding(28592));
                }
            }
            else
                return false;

            return true;
        }
        
        // zobrazí zdrojové soubory typu txt
        private bool OpenTextFile(string path, bool open_it)
        {
            if (!open_it)
            {
                File.Copy(path, @"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt");
                return true;
            }

            if (File.Exists(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt"))
            {
                if (open_it)
                {
                    GroupRight.Text = "Nalezený zdroj: \"" + Path.GetFileName(path) + "\"";
                    if (CheckForceEncoding.Checked && ComboEncoding.SelectedIndex != -1)
                        TextBoxSource.Text = File.ReadAllText(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt", Encoding.GetEncoding(ComboEncoding.SelectedItem.ToString()));
                    else
                        TextBoxSource.Text = File.ReadAllText(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt");
                }
                return true;
            }
            
            GroupRight.Text = "Nalezený zdroj: \"" + Path.GetFileName(path) + "\"";

            if (CheckForceEncoding.Checked && ComboEncoding.SelectedIndex != -1)
                TextBoxSource.Text = File.ReadAllText(path, Encoding.GetEncoding(ComboEncoding.SelectedItem.ToString()));
            else
                TextBoxSource.Text = File.ReadAllText(path);

            File.WriteAllText(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt", TextBoxSource.Text);

            return true;
        }

        // zobrazí zdrojové soubory typu html
        private bool OpenHTMLFile(string path, bool open_it)
        {
            // pokud již byl vytvořen text, přečte ho
            if (!CheckForceEncoding.Checked && File.Exists(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt"))
            {
                if (open_it)
                {
                    GroupRight.Text = "Nalezený zdroj: \"" + Path.GetFileName(path) + "\"";
                    TextBoxSource.Text = File.ReadAllText(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt");
                }
                return true;
            }

            string text = String.Empty;

            if (CheckForceEncoding.Checked && ComboEncoding.SelectedIndex != -1)
                text = File.ReadAllText(path, Encoding.GetEncoding(ComboEncoding.SelectedItem.ToString()));
            else
                text = File.ReadAllText(path);

            // odstraní prvky html
            Regex regexCss = new Regex("(\\<script(.+?)\\</script\\>)|(\\<style(.+?)\\</style\\>)", RegexOptions.Singleline | RegexOptions.IgnoreCase);
            text = regexCss.Replace(text, string.Empty);
            text = Regex.Replace(text, "<.*?>", string.Empty);
            text = Regex.Replace(text, @"^\s+$[\r\n]*", "", RegexOptions.Multiline);
            text = text.Replace("&nbsp;", string.Empty);

            File.WriteAllText(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt", text);

            if (open_it)
            {
                GroupRight.Text = "Nalezený zdroj: \"" + Path.GetFileName(path) + "\"";
                TextBoxSource.Text = text;
            }

            return true;
        }

        // zobrazí zdrojové soubory typu doc a docx
        private bool OpenDOCFile(string path, bool open_it)
        {
            // pokud již byl vytvořen text, přečte ho
            if (!CheckForceEncoding.Checked && File.Exists(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt"))
            {
                if (open_it)
                {
                    GroupRight.Text = "Nalezený zdroj: \"" + Path.GetFileName(path) + "\"";
                    TextBoxSource.Text = File.ReadAllText(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt");
                }
                return true;
            }

            TextExtractor extractor = new TextExtractor(path);
            string text = extractor.ExtractText();
            text = Regex.Replace(text, "<.*?>", string.Empty);
            File.WriteAllText(@"reports/" + Path.GetFileNameWithoutExtension(path) + ".txt", text);

            if (open_it)
            {
                GroupRight.Text = "Nalezený zdroj: \"" + Path.GetFileName(path) + "\"";
                TextBoxSource.Text = text;
            }

            return true;
        }

        // vytvoří soubor obsahující slova ze vstupního textu rozdělena do formy n-gramů, text převeden na čísla podle tabulky pro rychlejší práci
        // vytvořený soubor má znakovou sadu ascii, pro menší náročnost na místo
        private int CreateNGrams(string input_path, string output_path, int n, ref Dictionary<string, int> table)
        {
            string read_word = "";
            List<int> n_gram = new List<int>();
            int table_size = table.Count;
            int number_of_ngrams = 0;

            try
            {
                using (StreamReader reader = new StreamReader(input_path, Encoding.GetEncoding(28592)))
                {
                    // vytvoří prvních n prvků
                    for (int i = 0; i < n; i++)
                    {
                        while (reader.Peek() != ' ')
                        {
                            read_word += Convert.ToChar(reader.Read());
                        }
                        reader.Read();

                        if (table.ContainsKey(read_word))
                            n_gram.Add(table[read_word]);
                        else
                        {
                            n_gram.Add(table_size);
                            table.Add(read_word, table_size);
                            table_size++;
                        }

                        read_word = "";
                    }

                    for (int i = 0; i < n-1; i++)
                        File.AppendAllText(output_path, n_gram[i].ToString() + ',', Encoding.ASCII);
                    File.AppendAllText(output_path, n_gram[n - 1].ToString() + ';', Encoding.ASCII);
                    number_of_ngrams++;

                    Application.DoEvents();
                    
                    // smyčka pro zbytek textu
                    do
                    {
                        while (reader.Peek() != ' ')
                        {
                            read_word += Convert.ToChar(reader.Read());
                        }
                        reader.Read();

                        if (read_word == "")
                            continue;

                        n_gram.RemoveAt(0);

                        if (table.ContainsKey(read_word))
                            n_gram.Add(table[read_word]);
                        else
                        {
                            n_gram.Add(table_size);
                            table.Add(read_word, table_size);
                            table_size++;
                        }

                        for (int i = 0; i < n - 1; i++)
                            File.AppendAllText(output_path, n_gram[i].ToString() + ',', Encoding.ASCII);
                        File.AppendAllText(output_path, n_gram[n - 1].ToString() + ';', Encoding.ASCII);
                        number_of_ngrams++;

                        read_word = "";
                        Application.DoEvents();
                    }
                    while (reader.Peek() != -1);
                }
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Chyba: Nastala chyba při vytváření seznamu n-gramů.";
                File.Delete(output_path);
                return -1;
            }

            return (number_of_ngrams);
        }

        // porovnání dvou souborů ve formě n-gramů, porovnání nebere ohled na pořadí slov v n-gramu, vrací procentuální míru shodnosti
        private bool Compare2NGrams(string first_file, string second_file, ref IniReaderWriter iniprocessingunit, int n, bool silent)
        {
            uint number_of_positives = 0;
            uint number_of_positives_suspect = 0;
            Dictionary<int, List<List<int>>> ngrams_to_compare = new Dictionary<int, List<List<int>>>();
            string word_read = "";
            char char_read;
            int number_read = 0;
            int index_temp = 0;
            int position_in_text = 0;
            List<List<int>> ngrams_temp;
            List<int> current_ngram;
            List<List<KeyValuePair<List<int>, List<List<int>>>>> list_of_positives = new List<List<KeyValuePair<List<int>, List<List<int>>>>>();

            if (!silent)
            {
                StatusProgressBar.Value = 0;
                StatusProgressBar.Maximum = 6;
            }

            //vytvoření seznamu ngramů z druhého souboru
            //ngramy rozřazeny pod klíče podle hodnoty prvního prvku
            try
            {
                using (StreamReader reader = new StreamReader(second_file, Encoding.ASCII))
                {
                    do
                    {   // nalezení/vytvoření klíče pro první prvek ngramu
                        char_read = Convert.ToChar(reader.Read());
                        while (char_read != ',' && char_read != ';')
                        {
                            word_read += char_read;
                            char_read = Convert.ToChar(reader.Read());
                        }
                        number_read = Convert.ToInt32(word_read);

                        if (ngrams_to_compare.TryGetValue(number_read, out ngrams_temp))
                        {
                            ngrams_temp.Add(new List<int>());
                            index_temp = ngrams_temp.Count - 1;
                            ngrams_temp[index_temp].Add(number_read);
                        }
                        else
                        {
                            ngrams_temp = new List<List<int>>();
                            ngrams_temp.Add(new List<int>());
                            ngrams_temp[0].Add(number_read);
                            index_temp = 0;
                            ngrams_to_compare.Add(number_read, ngrams_temp);
                        }

                        //přidání zbytku ngramu
                        word_read = "";

                        while (char_read != ';')
                        {
                            char_read = Convert.ToChar(reader.Read());
                            while (char_read != ',' && char_read != ';')
                            {
                                word_read += char_read;
                                char_read = Convert.ToChar(reader.Read());
                            }
                            number_read = Convert.ToInt32(word_read);

                            ngrams_temp[index_temp].Add(number_read);
                            word_read = "";
                        }

                        // uložení pozice v textu jako poslední prvek
                        ngrams_temp[index_temp].Add(position_in_text++);
                        Application.DoEvents();
                    }
                    while (reader.Peek() != -1);
                }
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                if (!silent)
                    StatusText.Text = "Chyba: Nastala chyba při přípravě k porovnávání n-gramů.";
                return false;
            }

            if (!silent)
            {
                StatusProgressBar.Value = 1;
                Application.DoEvents();
            }

            //postupné čtení prvního souboru a počítání shod
            try
            {
                using (StreamReader reader = new StreamReader(first_file, Encoding.ASCII))
                {
                    position_in_text = 0;

                    do
                    {   //získání ngramu
                        current_ngram = new List<int>();
                        word_read = "";

                        char_read = '0';
                        while (char_read != ';')
                        {
                            char_read = Convert.ToChar(reader.Read());
                            while (char_read != ',' && char_read != ';')
                            {
                                word_read += char_read;
                                char_read = Convert.ToChar(reader.Read());
                            }
                            
                            number_read = Convert.ToInt32(word_read);
                            current_ngram.Add(number_read);
                            word_read = "";
                        }
                        current_ngram.Add(position_in_text++);

                        //nalezení podobných ngramů a porovnání
                        int last_index = 0;
                        List<List<int>> ngrams_copy;
                        bool is_positive = true;
                        bool is_new = true;

                        for (int i = 0; i < current_ngram.Count - 1; i++)
                        {
                            if (!ngrams_to_compare.TryGetValue(current_ngram[i], out ngrams_temp))
                            {
                                continue;
                            }

                            // vytvoření kopie ngramu
                            ngrams_copy = new List<List<int>>();
                            for (int a = 0; a < ngrams_temp.Count; a++)
                            {
                                ngrams_copy.Add(new List<int>());
                                for (int b = 0; b < ngrams_temp[a].Count - 1; b++ )
                                {
                                    ngrams_copy[a].Add(ngrams_temp[a][b]);
                                }
                            }

                            // porovnání ngramu s právě vyšetřovaným ngramem
                            for (int j = 0; j < ngrams_copy.Count; j++)
                            {
                                is_positive = true;

                                for (int k = current_ngram.Count - 2; k >= 0; k--)
                                {
                                    last_index = ngrams_copy[j].LastIndexOf(current_ngram[k]);
                                    if (last_index != -1)
                                    {
                                        ngrams_copy[j].RemoveAt(last_index);
                                    }
                                    else
                                    {
                                        is_positive = false;
                                        break;
                                    }
                                }

                                if (is_positive)
                                {
                                    //number_of_positives++;

                                    // řešení prvního prvku
                                    if (list_of_positives.Count == 0)
                                    {
                                        KeyValuePair<List<int>, List<List<int>>> temp = new KeyValuePair<List<int>, List<List<int>>>(new List<int>(), new List<List<int>>());
                                        foreach (int number in current_ngram)
                                        {
                                            temp.Key.Add(number);
                                        }
                                        temp.Value.Add(new List<int>());
                                        foreach (int number in ngrams_temp[j])
                                        {
                                            temp.Value[0].Add(number);
                                        }

                                        list_of_positives.Add(new List<KeyValuePair<List<int>, List<List<int>>>>());
                                        list_of_positives[list_of_positives.Count - 1].Add(temp);
                                    }
                                    else
                                    {
                                        int keyvaluepair_last = list_of_positives[list_of_positives.Count - 1].Count - 1;

                                        // napřed rozlišit jestli vytvořit nový shluk (přeskočit pokud jde stále o stejný ngram)
                                        // pak jestli je to nový ngram nebo stále stejný
                                        // odstranit poslední prvek pokud jsem už moc daleko a má tam jen 1 keyvaluepair

                                        // pokud tento ngram dosud neměl shodu a je dál než n od předchozího shluku, vytvoř nový shluk, a odstraň předchozí pokud má jen 1 prvek, jinak přidej shodu do předchozího shluku
                                        if (is_new)
                                        {
                                            KeyValuePair<List<int>, List<List<int>>> temp = new KeyValuePair<List<int>, List<List<int>>>(new List<int>(), new List<List<int>>());
                                            foreach (int number in current_ngram)
                                            {
                                                temp.Key.Add(number);
                                            }
                                            temp.Value.Add(new List<int>());
                                            foreach (int number in ngrams_temp[j])
                                            {
                                                temp.Value[0].Add(number);
                                            }

                                            if ((current_ngram[n] - list_of_positives[list_of_positives.Count - 1][keyvaluepair_last].Key[n]) > n)
                                            {
                                                if (list_of_positives[list_of_positives.Count - 1].Count == 1)
                                                    list_of_positives.RemoveAt(list_of_positives.Count - 1);

                                                list_of_positives.Add(new List<KeyValuePair<List<int>, List<List<int>>>>());
                                            }

                                            list_of_positives[list_of_positives.Count - 1].Add(temp);
                                        }
                                        else        // ngram už v listu existuje jako shoda, přidá se jen další prvek do listu ve Value
                                        {
                                            List<int> temp2 = new List<int>();
                                            foreach (int number in ngrams_temp[j])
                                            {
                                                temp2.Add(number);
                                            }

                                            list_of_positives[list_of_positives.Count - 1][keyvaluepair_last].Value.Add(temp2);
                                        }
                                    }

                                    is_new = false;
                                }
                            }
                        }
                        Application.DoEvents();
                    }
                    while (reader.Peek() != -1);
                }

                foreach (List<KeyValuePair<List<int>, List<List<int>>>> cluster in list_of_positives)
                {
                    number_of_positives_suspect += Convert.ToUInt32(cluster.Count);
                }

                number_of_positives = number_of_positives_suspect;

                if (!silent)
                {
                    StatusProgressBar.Value = 2;
                    Application.DoEvents();
                }

                // filtrace shod
                // vytvoření seznamu pozic
                List<int> source_positions = new List<int>();
                List<int> positions_to_remove = new List<int>();

                foreach (List<KeyValuePair<List<int>, List<List<int>>>> cluster in list_of_positives)
                {
                    foreach (KeyValuePair<List<int>, List<List<int>>> positive in cluster)
                    {
                        foreach (List<int> source_positive in positive.Value)
                        {
                            source_positions.Add(source_positive[n]);
                        }
                    }
                }
                source_positions.Sort();

                Application.DoEvents();

                for (int i = source_positions.Count - 1; i >= 0; i--)
                {
                    if (i == 0)
                        break;

                    if (source_positions[i] == source_positions[i - 1])
                        source_positions.RemoveAt(i);
                }

                // uložení shodných slov pro jejich následné zobrazení v textboxu
                int file_num = Int32.Parse(Regex.Match(second_file, @"\d+").Value);
                SavePositives(String.Format("reports\\file{0}_clean.txt", file_num), String.Format("reports\\file{0}_positives.txt", file_num), source_positions, n);
                List<int> suspect_positions_temp = new List<int>();

                foreach (List<KeyValuePair<List<int>, List<List<int>>>> cluster in list_of_positives)
                {
                    foreach (KeyValuePair<List<int>, List<List<int>>> positive in cluster)
                    {

                        suspect_positions_temp.Add(positive.Key[n]);
                    }
                }
                suspect_positions_temp.Sort();
                SavePositives("Cleaned.txt", String.Format("Positives_file{0}.txt", file_num), suspect_positions_temp, n);

                Application.DoEvents();

                if (!silent)
                {
                    StatusProgressBar.Value = 3;
                    Application.DoEvents();
                }

                // nalezení pozic k odstranění
                for (int i = 0; i < source_positions.Count; i++)
                {
                    if (i == 0)
                    {
                        if (source_positions.Count == 1 || source_positions[1] - source_positions[0] > n)
                            positions_to_remove.Add(source_positions[0]);
                    }
                    else if (i == (source_positions.Count - 1))
                    {
                        if (source_positions[i] - source_positions[i - 1] > n)
                            positions_to_remove.Add(source_positions[i]);
                    }
                    else
                    {
                        if ( source_positions[i] - source_positions[i - 1] > n && source_positions[i + 1] - source_positions[i] > n)
                            positions_to_remove.Add(source_positions[i]);
                        else if (i < (source_positions.Count - 2) && source_positions[i] - source_positions[i - 1] > n && source_positions[i + 2] - source_positions[i + 1] > n)
                            positions_to_remove.Add(source_positions[i]);
                        else if (i > 1 && source_positions[i+1] - source_positions[i] > n && source_positions[i - 1] - source_positions[i - 2] > n)
                            positions_to_remove.Add(source_positions[i]);
                    }
                }
                Application.DoEvents();

                // odstranění nalezených pozic
                foreach (List<KeyValuePair<List<int>, List<List<int>>>> cluster in list_of_positives)
                {
                    foreach (KeyValuePair<List<int>, List<List<int>>> positive in cluster)
                    {
                        for (int i = positive.Value.Count - 1; i >= 0; i-- )
                        {
                            if (positions_to_remove.Contains(positive.Value[i][n]))
                                positive.Value.RemoveAt(i);
                        }
                    }

                    for (int i = cluster.Count - 1; i >= 0; i--)
                    {
                        if (cluster[i].Value.Count == 0)
                            cluster.RemoveAt(i);
                    }
                }
                Application.DoEvents();

                for (int i = list_of_positives.Count - 1; i >= 0; i--)
                {
                    if (list_of_positives[i].Count == 0)
                        list_of_positives.RemoveAt(i);
                }

                if (!silent)
                {
                    StatusProgressBar.Value = 4;
                    Application.DoEvents();
                }

                // vyhodnocení shluků shod
                source_positions = new List<int>();
                List<int> suspect_positions = new List<int>(); 

                foreach (List<KeyValuePair<List<int>, List<List<int>>>> cluster in list_of_positives)
                {
                    foreach (KeyValuePair<List<int>, List<List<int>>> positive in cluster)
                    {
                        suspect_positions.Add(positive.Key[n]);

                        foreach (List<int> source_positive in positive.Value)
                        {
                            source_positions.Add(source_positive[n]);
                        }
                    }
                }
                Application.DoEvents();

                source_positions.Sort();
                suspect_positions.Sort();

                for (int i = source_positions.Count - 1; i > 0; i--)
                {
                    if (source_positions[i] == source_positions[i - 1])
                        source_positions.RemoveAt(i);
                }

                int suspect_score = 0;
                int source_score = 0;
                int temporary = 0;

                for (int i = 0; i < (suspect_positions.Count - 2); i++)
                {
                    if (suspect_positions[i + 1] - suspect_positions[i] < n)
                    {
                        if (temporary == 0)
                            temporary = n + 1 - (suspect_positions[i + 1] - suspect_positions[i]);
                        else
                            temporary = temporary * (n + 1 - (suspect_positions[i + 1] - suspect_positions[i]));
                    }
                    else
                    {
                        suspect_score += temporary;
                        temporary = 0;
                    }

                    if (suspect_score + temporary > 2000000000)
                        break;
                }
                Application.DoEvents();

                if (temporary > 0)
                {
                    suspect_score += temporary;
                    temporary = 0;
                }
                if (suspect_score < 0)
                    suspect_score = int.MaxValue;

                for (int i = 0; i < (source_positions.Count - 2); i++)
                {
                    if (source_positions[i + 1] - source_positions[i] < n)
                    {
                        if (temporary == 0)
                            temporary = n + 1 - (source_positions[i + 1] - source_positions[i]);
                        else
                            temporary = temporary * (n + 1 - (source_positions[i + 1] - source_positions[i]));
                    }
                    else
                    {
                        source_score += temporary;
                        temporary = 0;
                    }

                    if (source_score + temporary > 2000000000)
                        break;
                }
                Application.DoEvents();

                if (temporary > 0)
                {
                    source_score += temporary;
                }
                if (source_score < 0)
                    source_score = int.MaxValue;

                if (!silent)
                {
                    StatusProgressBar.Value = 5;
                    Application.DoEvents();
                }

                iniprocessingunit.ChangeKeyValue("Results", "NumofPositives", number_of_positives.ToString());

                double cos_similiarity = (Convert.ToDouble(number_of_positives) / Convert.ToInt32(iniprocessingunit.GetKeyValue("Results", "SourceNGrams"))) * (Convert.ToDouble(number_of_positives_suspect) / Convert.ToInt32(iniprocessingunit.GetKeyValue("Results", "SuspectNGrams")));
                if (cos_similiarity > 1)
                    cos_similiarity = 1;

                iniprocessingunit.ChangeKeyValue("Results", "CosSimiliarity", String.Format("{0:0.0000}", cos_similiarity));

                if (suspect_score > source_score)
                    iniprocessingunit.ChangeKeyValue("Results", "ClusterScore", suspect_score.ToString());
                else
                    iniprocessingunit.ChangeKeyValue("Results", "ClusterScore", source_score.ToString());
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                if (!silent)
                    StatusText.Text = "Chyba: Nastala chyba při porovnávání n-gramů.";
                return false;
            }

            if (!silent)
            {
                StatusProgressBar.Value = 6;
                Application.DoEvents();
            }

            return true;
        }

        // Aktualizuje informace o výsledcích z ini souboru
        private void UpdateResults(string source_ini_path)
        {
            IniReaderWriter iniprocessingunit = new IniReaderWriter();

            try
            {
                iniprocessingunit.ReadIniFile(source_ini_path);

                LabelSuspectNGrams.Text = iniprocessingunit.GetKeyValue("Results", "SuspectNGrams");

                LabelSourceNGrams.Text = iniprocessingunit.GetKeyValue("Results", "SourceNGrams");
                LabelSourceN.Text = iniprocessingunit.GetKeyValue("Results", "UsedN");
                LabelSourcePositives.Text = iniprocessingunit.GetKeyValue("Results", "NumofPositives");
                LabelSourceCos.Text = iniprocessingunit.GetKeyValue("Results", "CosSimiliarity");
                LabelClusterScore.Text = iniprocessingunit.GetKeyValue("Results", "ClusterScore");
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Chyba: Nelze přečíst výsledky předchozího porovnání.";
            }
        }

        // označuje vybraný zdroj jako čistý, podezřelý a velmi podezřelý
        private void SourceSelectedUpdate()
        {
            List<string> dl_files = new List<string>();
            dl_files = (Directory.GetFiles("download")).ToList<string>();
            dl_files.Sort((x, y) => ExtractNumber(x).CompareTo(ExtractNumber(y)));

            string extension = Path.GetExtension(dl_files[Convert.ToInt32(NumSourceSelect.Value)]);
            if (extension.Length > 0)
                LabelSourceType.Text = extension.Substring(1);
            else
                LabelSourceType.Text = "soubor";
            LabelSourceState.Text = "N/A";

            if (CheckCosSim.Checked || CheckClusterScore.Checked)
            {
                IniReaderWriter iniprocessingunit = new IniReaderWriter();
                int alert = 0;

                try
                {
                    string[] files = Directory.GetFiles("reports", "*.ini");

                    foreach (string file in files)
                    {
                        if (file.IndexOf("file" + NumSourceSelect.Value.ToString() + "_") != -1)
                        {
                            iniprocessingunit.ReadIniFile(file);

                            if (CheckCosSim.Checked)
                            {
                                if ((NumericCosSimLimit.Value / 100) <= decimal.Parse(iniprocessingunit.GetKeyValue("Results", "CosSimiliarity")))
                                    alert++;
                            }
                            if (CheckClusterScore.Checked)
                            {
                                if ((Convert.ToInt32(ComboClusterScoreLimit.SelectedItem) <= int.Parse(iniprocessingunit.GetKeyValue("Results", "ClusterScore"))))
                                    alert++;
                            }

                            switch (alert)
                            {
                                case 0: LabelSourceState.Text = "Čistý"; break;
                                case 1: LabelSourceState.Text = "Podezřelý"; break;
                                case 2: LabelSourceState.Text = "Velmi podezřelý"; break;
                            }

                            UpdateResults(file);
                            return;
                        }
                    }

                    LabelSourceNGrams.Text = "0";
                    LabelSourceN.Text = "0";
                    LabelSourcePositives.Text = "0";
                    LabelSourceCos.Text = "0,0 %";
                    LabelClusterScore.Text = "0";
                }
                catch (Exception ex)
                {
                    System.Media.SystemSounds.Hand.Play();
                    File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                    StatusText.Text = "Chyba: Nelze přečíst výsledky předchozího porovnání.";
                }
            }
        }

        // otevře source_path, čte slova, ukládá slova na zadaných pozicích do output, oddělené čárkami
        private void SavePositives(string source_path, string output_path, List<int> positions, int n)
        {
            string read_word = "";
            int counter = 0;
            int list_counter = 0;

            try
            {
                using (StreamReader reader = new StreamReader(source_path, Encoding.GetEncoding(28592)))
                {
                    do
                    {
                        while (reader.Peek() != ' ')
                        {
                            read_word += Convert.ToChar(reader.Read());
                        }
                        reader.Read();

                        if (read_word == "")
                            continue;

                        if (list_counter == positions.Count)
                            break;

                        if (counter >= positions[list_counter])
                        {
                            File.AppendAllText(output_path, read_word + ",", Encoding.GetEncoding(28592));

                            if (counter == (positions[list_counter] + n - 1))
                            {
                                list_counter++;
                            }
                        }

                        counter++;
                        read_word = "";
                        Application.DoEvents();
                    } 
                    while (reader.Peek() != -1);
                }
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Chyba: Nastala chyba při ukládání nalezených shodných slov.";
                File.Delete(output_path);
                return;
            }
        }

        // označí shody v zobrazeném textu
        private void MarkPositivesinText(int file_number)
        {
            StatusText.Text = "Probíhá označování shod v textu. Čekejte prosím.";
            StatusProgressBar.Value = 0;
            StatusProgressBar.Maximum = 4;
            Application.DoEvents();

            try
            {
                string read_word = "";
                List<string> positives = new List<string>();
                int index, start_index = 0, counter = 0;

                using (StreamReader reader = new StreamReader(String.Format("Positives_file{0}.txt", file_number), Encoding.GetEncoding(28592)))
                {
                    do
                    {
                        while (reader.Peek() != ',')
                        {
                            read_word += Convert.ToChar(reader.Read());
                        }
                        reader.Read();

                        positives.Add(read_word);

                        read_word = "";
                    }
                    while (reader.Peek() != -1);
                }
                StatusProgressBar.Value = 1;
                Application.DoEvents();

                while (counter < positives.Count)
                {
                    index = TextBoxSuspect.Text.IndexOf(positives[counter], start_index, StringComparison.OrdinalIgnoreCase);

                    if (index == -1)
                    {
                        counter++;
                        continue;
                    }

                    TextBoxSuspect.Select(index, positives[counter].Length);
                    TextBoxSuspect.SelectionBackColor = Color.Yellow;

                    start_index = index + positives[counter].Length;
                    counter++;
                }
                StatusProgressBar.Value = 2;
                Application.DoEvents();

                positives.Clear();
                counter = 0;
                start_index = 0;
                read_word = "";

                using (StreamReader reader = new StreamReader(String.Format("reports\\file{0}_positives.txt", file_number), Encoding.GetEncoding(28592)))
                {
                    do
                    {
                        while (reader.Peek() != ',')
                        {
                            read_word += Convert.ToChar(reader.Read());
                        }
                        reader.Read();

                        positives.Add(read_word);

                        read_word = "";
                    }
                    while (reader.Peek() != -1);
                }
                StatusProgressBar.Value = 3;
                Application.DoEvents();

                while (counter < positives.Count)
                {
                    index = TextBoxSource.Text.IndexOf(positives[counter], start_index, StringComparison.OrdinalIgnoreCase);

                    if (index == -1)
                    {
                        counter++;
                        continue;
                    }

                    TextBoxSource.Select(index, positives[counter].Length);
                    TextBoxSource.SelectionBackColor = Color.Yellow;

                    start_index = index + positives[counter].Length;
                    counter++;
                }
                StatusProgressBar.Value = 4;
                Application.DoEvents();
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
                StatusText.Text = "Chyba: Nastala chyba při označování shodných slov v zobrazeném textu.";
                return;
            }

            StatusText.Text = "Označování shod dokončeno.";
        }

        // aktualizace panelu zdrojů
        private void UpdateSources()
        {
            List<string> files = new List<string>();
            files = (Directory.GetFiles("download")).ToList<string>();
            files.Sort((x, y) => ExtractNumber(x).CompareTo(ExtractNumber(y)));

            if (files.Count == 0)
            {
                NumSourceSelect.Value = 0;
                LabelSourceType.Text = "N/A";
                NumSourceSelect.Enabled = false;
                ButtonSourceComp.Enabled = false;
                ButtonSourceView.Enabled = false;
            }
            else
            {
                NumSourceSelect.Value = 0;
                NumSourceSelect.Maximum = files.Count - 1;
                NumSourceSelect.Enabled = true;
                ButtonSourceComp.Enabled = true;
                ButtonSourceView.Enabled = true;
                LabelSourceType.Text = Path.GetExtension(files[0]).Substring(1);
            }
        }

        // podpůrná metoda pro seřazení listu podle čísel ve stringu
        static int ExtractNumber(string text)
        {
            Match match = Regex.Match(text, @"(\d+)");

            int value;
            if (!int.TryParse(match.Value, out value))
            {
                return 0;
            }

            return value;
        }

        // podpůrná metoda pro vypnutí / zapnutí interface
        public void DisableEnableControls(bool enable)
        {
            running = !enable;
            ButtonOpen.Enabled = enable;
            ButtonSearch.Enabled = enable;
            ButtonCompareAll.Enabled = enable;
            ButtonOpenLast.Enabled = enable;
            CheckCompare.Enabled = enable;
            CheckShowSearch.Enabled = enable;
            ButtonSystemReset.Enabled = enable;
            ButtonStop.Enabled = !enable;
        }

        private void SearchResultSummary(string file_name, TimeSpan time, int files_failed, List<string> list_links_to_source)
        {
            List<string> files_downloaded = new List<string>();
            files_downloaded = (Directory.GetFiles("download")).ToList<string>();
            files_downloaded.Sort((x, y) => ExtractNumber(x).CompareTo(ExtractNumber(y)));
            string[] results = Directory.GetFiles("reports", "*.ini");
            string matching_name = "";
            int i = 0, j = 0, k = 0;
            IniReaderWriter iniprocessingunit = new IniReaderWriter();

            while (Directory.Exists("results\\" + Path.GetFileNameWithoutExtension(file_name) + matching_name))
            {
                matching_name = i.ToString();
                i++;
            }
            matching_name = "results\\" + Path.GetFileNameWithoutExtension(file_name) + matching_name;
            Directory.CreateDirectory(matching_name);
            Directory.CreateDirectory(matching_name + "\\download");
            Directory.CreateDirectory(matching_name + "\\reports");
            File.Copy("Original.txt", matching_name + "\\Original.txt");
            File.Copy("PlagSearcherPro_Config.ini", matching_name + "\\PlagSearcherPro_Config.ini");


            File.AppendAllText("Result_Summary.txt", "\r\n\r\n\r\n#--- " + file_name + " ---#\r\n");
            File.AppendAllText("Result_Summary.txt", "Celkový čas: " + time.TotalMinutes + " min\r\n");
            File.AppendAllText("Result_Summary.txt", "Celkem staženo: " + files_downloaded.Count + " souborů\r\n");
            File.AppendAllText("Result_Summary.txt", "Z toho selhalo: " + files_failed + " stažení\r\n");
            File.AppendAllText("Result_Summary.txt", "Celkem porovnáno: " + results.Length + " zdrojů\r\n");
            File.AppendAllText("Result_Summary.txt", "Použité n-gramy: " + TrackNValue.Value + "-gramy\r\n");
            File.AppendAllText("Result_Summary.txt", "----------\r\n");

            try
            {
                for (i = 0; i < results.Length; i++)
                {
                    iniprocessingunit.ReadIniFile(results[i]);
                    j = Convert.ToInt32(Regex.Match(Path.GetFileName(results[i]), "\\d+").Value);

                    File.AppendAllText("Result_Summary.txt", "Zdroj č." + i + "\r\nPočet n-gramů podezřelého dokumentu: " + iniprocessingunit.GetKeyValue("Results", "SuspectNGrams") +
                                                                "; Počet n-gramů zdroje: " + iniprocessingunit.GetKeyValue("Results", "SourceNGrams") +
                                                                "; Počet pozitiv: " + iniprocessingunit.GetKeyValue("Results", "NumofPositives") +
                                                                "; Kosinová shodnost: " + iniprocessingunit.GetKeyValue("Results", "CosSimiliarity") +
                                                                "; Míra shluků shod: " + iniprocessingunit.GetKeyValue("Results", "ClusterScore") + 
                                                                "; Odkaz: " + list_links_to_source[j] + "\r\n");

                    if (Convert.ToInt32(iniprocessingunit.GetKeyValue("Results", "ClusterScore")) > 999)
                    {
                        File.Copy(String.Format("Positives_file{0}.txt", j), matching_name + String.Format("\\Positives_file{0}.txt", k));
                        File.Copy(String.Format("reports\\file{0}.txt", j), matching_name + String.Format("\\reports\\file{0}.txt", k));
                        File.Copy(String.Format("reports\\file{0}_positives.txt", j), matching_name + String.Format("\\reports\\file{0}_positives.txt", k));
                        File.Copy(String.Format("reports\\file{0}_result.ini", j), matching_name + String.Format("\\reports\\file{0}_result.ini", k));
                        File.Create(matching_name + String.Format("\\download\\file{0}.txt", k));
                        k++;
                    }

                    iniprocessingunit.FlushIniData();
                }
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Hand.Play();
                File.AppendAllText("Error_log.txt", ex.Message + "\r\n");
            }
        }

        private bool IsFileInUse(FileInfo file)
        {
            FileStream stream = null;

            try
            {
                stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
            }
            catch (IOException)
            {
                return true;
            }
            finally
            {
                if (stream != null)
                    stream.Close();
            }

            return false;
        }
    }
}
