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

namespace Binary_Search
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // Metoda akceptuje argument w postaci ciągu tekstowego.
        // Używa algorytm sortowania przez wybieranie do posorotwania tablicy.
        private void SelectionSort(string[] sArray)
        {
            int minIndex;      // Indeks najmniejszej wartości w analizowanych danych.
            string minValue;   // Najmniejsza wartość w analizowanych danych.

            // Pętla zewnętrzna przeprowadza iterację przez wszystkie elementy tablicy,
            // z wyłączeniem ostatniego. Zmienna startScan wskazuje położenie, od
            // którego powinna rozpocząć się iteracja.
            for (int startScan = 0; startScan < sArray.Length - 1; startScan++)
            {
                // Przyjmujemy założenie, że pierwszy element w analizowanym
                // fragmencie tablicy zawiera najmniejszą wartość.
                minIndex = startScan;
                minValue = sArray[startScan];

                // Sprawdzenie tablicy, począwszy od drugiego elementu w analizowanym
                // fragmencie tablicy, i odszukanie najmniejszej wartości.
                for (int index = startScan + 1; index < sArray.Length; index++)
                {
                    if (string.Compare(sArray[index], minValue, true) < 0)
                    {
                        minValue = sArray[index];
                        minIndex = index;
                    }
                }

                // Swap the element with the lesser value with the
                // first element in the scannable area.
                Swap(ref sArray[minIndex], ref sArray[startScan]);
            }
        }

        // Zamiana elementów miejscami: tego o najmniejszej wartości
        // z pierwszym znajdującym się w analizowanym fragmencie tablicy.
        private void Swap(ref string a, ref string b)
        {
            string temp = a;
            a = b;
            b = temp;
        }

        // Metoda BinarySearch() szuka wartości w tablicy ciągów tekstowych.
        // Jeżeli wartość zostanie znaleziona, metoda zwraca jej położenie.
        // W przeciwnym razie wartością zwrotną jest -1.
        private int BinarySearch(string[] sArray, string value)
        {
            int first = 0;                // Pierwszy element tablicy.
            int last = sArray.Length - 1; // Ostatni element tablicy.
            int middle;                   // Punkt środkowy operacji wyszukiwania.
            int position = -1;            // Położenie szukanej wartości.
            bool found = false;           // Zmienna wskazująca na znalezienie szukanej wartości.

            // Szukanie wartości.
            while (!found && first <= last)
            {
                // Obliczenie punkt środkowego.
                middle = (first + last) / 2;

                // Jeżeli szukana wartość znajduje się w punkcie środkowym…
                if (string.Compare(sArray[middle], value, true) == 0)
                {
                    found = true;
                    position = middle;
                }
                // Jeżeli szukana wartość znajduje się w pierwszej połowie tabeli…
                else if (string.Compare(sArray[middle], value, true) > 0)
                {
                    last = middle - 1;
                }
                // Jeżeli szukana wartość znajduje się w drugiej połowie tabeli…
                else
                {
                    first = middle + 1;
                }
            }

            // Zwrot położenia elementu lub wartości -1,
            // jeżeli nie został znaleziony w tablicy.
            return position;
        }

        // Metoda ReadNames() odczytuje dane z pliku
        // i umieszcza je w tablicy podanej jako argument.
        private void ReadNames(string[] sArray)
        {
            try
            {
                // Zmienna licznika używana w pętli.
                int index = 0;

                // Deklaracja zmiennej typu StreamReader.
                StreamReader inputFile;

                // Otworzenie pliku i pobranie obiektu typu StreamReader.
                inputFile = File.OpenText("Names.txt");

                // Umieszczenie zawartości pliku w tablicy.
                while (index < sArray.Length && !inputFile.EndOfStream)
                {
                    sArray[index] = inputFile.ReadLine();
                    index++;
                }

                // Zamknięcie pliku.
                inputFile.Close();
            }
            catch (Exception ex)
            {
                // Wyświetlenie komunikatu błędu.
                MessageBox.Show(ex.Message);
            }
        }

        private void searchButton_Click(object sender, EventArgs e)
        {
            // Utworzenie tablicy przechowującej listę danych osób.
            const int SIZE = 40;
            string[] names = new string[SIZE];

            // Pobranie szukanych danych osoby.
            string searchValue = searchTextBox.Text;

            // Odczyt danych z pliku i umieszczenie ich w tablicy.
            ReadNames(names);

            // Sortowanie danych.
            SelectionSort(names);

            // Szukanie konkretnej osoby.
            if (BinarySearch(names, searchValue) != -1)
            {
                MessageBox.Show("Osoba " + searchValue + " została znaleziona w pliku.");
            }
            else
            {
                   MessageBox.Show("Osoba " + searchValue + " nie została znaleziona w pliku.");
            }
        }

        private void exitButton_Click(object sender, EventArgs e)
        {
            // Zamknięcie formularza.
            this.Close();
        }
    }
}
