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

using System.IO;

namespace FileListBoxDemo
{
    public partial class FileListBox : UserControl
    {
        #region Pola prywatne
        //wewnętrzne
        private string[] listaKatalogow = null;
        private string[] listaPlikow = null;
        private string[] listaDyskow = null;
        private bool pokazujDwieKropki = true;
        //konfigurowanie komponentu
        private string sciezkaKatalogu = null;
        private bool uwzglednijKatalogi = true;
        private bool uwzglednijPliki = true;
        private bool uwzglednijDyski = true;
        private bool uwzglednijKatalogNadrzedny = true;
        private string filtr = null;

        private bool mozliweZmienianieKatalogow = true;
        #endregion

        #region Metody prywatne
        private void PobierzZawartoscKatalogu()
        {
            if (sciezkaKatalogu == null)
                sciezkaKatalogu = Directory.GetCurrentDirectory();

            pokazujDwieKropki = (sciezkaKatalogu != Path.GetPathRoot(sciezkaKatalogu)
                               && uwzglednijKatalogNadrzedny);

            if (!Directory.Exists(sciezkaKatalogu))
                throw new DirectoryNotFoundException("Katalog " + sciezkaKatalogu + " nie istnieje!");

            listBox1.Items.Clear();

            if (uwzglednijKatalogi)
            {
                if (pokazujDwieKropki) listBox1.Items.Add("[..]");
                listaKatalogow = Directory.GetDirectories(sciezkaKatalogu);
                Array.Sort(listaKatalogow);
                //listBox1.Items.AddRange(listaKatalogow);
                foreach (string katalog in listaKatalogow)
                    listBox1.Items.Add("[" + Path.GetFileName(katalog) + "]");
            }
            if (uwzglednijPliki)
            {
                //listaPlikow = Directory.GetFiles(sciezkaKatalogu);
                if (filtr != null)
                    listaPlikow = Directory.GetFiles(sciezkaKatalogu, filtr);
                else
                    listaPlikow = Directory.GetFiles(sciezkaKatalogu);
                Array.Sort(listaPlikow);
                //listBox1.Items.AddRange(listaPlikow);
                foreach (string plik in listaPlikow)
                    listBox1.Items.Add(Path.GetFileName(plik));
            }
            if (uwzglednijDyski)
            {
                listaDyskow = Directory.GetLogicalDrives();
                //listBox1.Items.AddRange(listaDyskow);
                foreach (string dysk in listaDyskow)
                    listBox1.Items.Add("<" + dysk.Substring(0, 2) + ">");

            }
        }
        #endregion

        public FileListBox()
        {
            InitializeComponent();
            
            //sciezkaKatalogu = "C:\\Documents and Settings\\Jacek Matulewski\\Moje dokumenty\\Moje obrazy";
            //sciezkaKatalogu = "C:\\Documents and Settings\\Dom\\Moje dokumenty\\Moje obrazy";
            //filtr = "*.jpg";
            
            //sciezkaKatalogu = "C:\\";
            //filtr = "*.sys";
            
            PobierzZawartoscKatalogu();
        }

        private void listBox1_DoubleClick(object sender, EventArgs e)
        {
            if (!mozliweZmienianieKatalogow) return;

            int przesuniecie = (pokazujDwieKropki && uwzglednijKatalogi) ? 1 : 0;
            int numer = listBox1.SelectedIndex - przesuniecie; //+1 dla [..]
            int poczatekPlikow = (uwzglednijKatalogi ? listaKatalogow.Length : 0);
            int poczatekDyskow =
               poczatekPlikow + (uwzglednijPliki ? listaPlikow.Length : 0);

            //zmiana katalogu
            string nowaSciezkaKatalogu = null;
            if (numer == -1) nowaSciezkaKatalogu = sciezkaKatalogu + "\\..";
            if (numer >= 0 && numer < poczatekPlikow)
                nowaSciezkaKatalogu = listaKatalogow[numer];
            if (numer >= poczatekDyskow)
                nowaSciezkaKatalogu = listaDyskow[numer - poczatekDyskow];
            if (nowaSciezkaKatalogu != null
                  && Directory.Exists(nowaSciezkaKatalogu))
            {
                sciezkaKatalogu = Path.GetFullPath(nowaSciezkaKatalogu);
                PobierzZawartoscKatalogu();
                OnZmianaKatalogu(this, e);
            }

            //dwukrotne kliknięcie pliku
            string sciezkaPliku = null;
            if (numer >= poczatekPlikow && numer < poczatekDyskow)
                sciezkaPliku = listaPlikow[numer - poczatekPlikow];
            if (sciezkaPliku != null && File.Exists(sciezkaPliku))
                this.DwukrotneKliknieciePliku(this, e, Path.GetFullPath(sciezkaPliku));
        }

        #region Wlasciwosci
        [
           Category("Katalog"),
           Description("Wskazuje katalog prezentowany w kontrolce.")
        ]
        public string ŚcieżkaKatalogu
        {
            set
            {
                this.sciezkaKatalogu = value;
                PobierzZawartoscKatalogu();
                OnZmianaKatalogu(this, new EventArgs());
            }
            get
            {
                return this.sciezkaKatalogu;
            }
        }

        [
            Category("Katalog"),
            Description("Maska plików widocznych w komponencie.")
        ]
        public string Filtr
        {
            set
            {
                this.filtr = value;
                PobierzZawartoscKatalogu();
            }
            get
            {
                return this.filtr;
            }
        }

        [
            Category("Katalog"),
            Description("Decyduje o pokazaniu lub ukryciu listy katalogów.")
        ]
        public bool KatalogiWidoczne
        {
            set
            {
                this.uwzglednijKatalogi = value;
                PobierzZawartoscKatalogu();
            }
            get
            {
                return this.uwzglednijKatalogi;
            }
        }

        [
            Category("Katalog"),
            Description("Decyduje o pokazaniu lub ukryciu listy plików.")
        ]
        public bool PlikiWidoczne
        {
            set
            {
                this.uwzglednijPliki = value;
                PobierzZawartoscKatalogu();
            }
            get
            {
                return this.uwzglednijPliki;
            }
        }

        [
            Category("Katalog"),
            Description("Decyduje o pokazaniu lub ukryciu listy dysków.")
        ]
        public bool DyskiWidoczne
        {
            set
            {
                this.uwzglednijDyski = value;
                PobierzZawartoscKatalogu();
            }
            get
            {
                return this.uwzglednijDyski;
            }
        }

        [
            Category("Katalog"),
            Description("Decyduje o pokazaniu lub ukryciu katalogu nadrzędnego (dwóch kropek).")
        ]
        public bool KatalogNadrzędnyWidoczny
        {
            set
            {
                this.uwzglednijKatalogNadrzedny = value;
                PobierzZawartoscKatalogu();
            }
            get
            {
                return this.uwzglednijKatalogNadrzedny;
            }
        }

        [
            Category("Katalog"),
            Description("Decyduje o tym, czy możliwa jest eksploracja katalogów.")
        ]
        public bool MożliwaZmianaKatalogu
        {
            set
            {
                this.mozliweZmienianieKatalogow = value;
            }
            get
            {
                return this.mozliweZmienianieKatalogow;
            }
        }

        [
            Category("Katalog"),
            Description("Ścieżka zaznaczonego katalogu lub pliku.")
        ]
        public string ŚcieżkaDoZaznaczonegoElementu
        {
            get
            {
                int przesuniecie = (pokazujDwieKropki && uwzglednijKatalogi) ? 1 : 0;
                int numer = listBox1.SelectedIndex - przesuniecie; //+1 dla [..]
                int poczatekPlikow = (uwzglednijKatalogi ? listaKatalogow.Length : 0);
                int poczatekDyskow = poczatekPlikow + (uwzglednijPliki ? listaPlikow.Length : 0);

                string pelnaSciezka = null;
                if (numer == -1 && przesuniecie == 1)
                    pelnaSciezka = sciezkaKatalogu + "\\..";
                if (numer >= 0 && numer < poczatekPlikow)
                    pelnaSciezka = listaKatalogow[numer];
                if (numer >= poczatekPlikow && numer < poczatekDyskow)
                    pelnaSciezka = listaPlikow[numer - poczatekPlikow];
                if (numer >= poczatekDyskow)
                    pelnaSciezka = listaDyskow[numer - poczatekDyskow];

                if (pelnaSciezka == null) return "";

                return Path.GetFullPath(pelnaSciezka);
            }
        }
        #endregion

        #region Zdarzenia
        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.OnClick(e);
            this.OnZmianaZaznaczonegoElementu(sender, e);
        }

        private void listBox1_MouseDown(object sender, MouseEventArgs e)
        {
            this.OnMouseDown(e);
        }

        private void listBox1_MouseEnter(object sender, EventArgs e)
        {
            this.OnMouseEnter(e);
        }

        private void listBox1_MouseHover(object sender, EventArgs e)
        {
            this.OnMouseHover(e);
        }

        private void listBox1_MouseLeave(object sender, EventArgs e)
        {
            this.OnMouseLeave(e);
        }

        private void listBox1_MouseMove(object sender, MouseEventArgs e)
        {
            this.OnMouseMove(e);
        }

        private void listBox1_MouseUp(object sender, MouseEventArgs e)
        {
            this.OnMouseUp(e);
        }

        private void listBox1_KeyDown(object sender, KeyEventArgs e)
        {
            this.OnKeyDown(e);
        }

        private void listBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            this.OnKeyPress(e);
        }

        private void listBox1_KeyUp(object sender, KeyEventArgs e)
        {
            this.OnKeyUp(e);
        }

        public delegate void ZmianaZaznaczonegoElementuEventHandler(object sender, EventArgs e);

        [
            Category("Katalog"),
            Description("Następuje po zmianie zaznaczonego elementu.")
        ]
        public event ZmianaZaznaczonegoElementuEventHandler ZmianaZaznaczonegoElementu;

        protected virtual void OnZmianaZaznaczonegoElementu(object sender, EventArgs e)
        {
            if (ZmianaZaznaczonegoElementu != null) ZmianaZaznaczonegoElementu(this, e);
        }

        [
            Category("Katalog"),
            Description("Występuje przy zmianie prezentowanego katalogu.")
        ]
        public event EventHandler ZmianaKatalogu;
        protected virtual void OnZmianaKatalogu(object sender, EventArgs e)
        {
            if (ZmianaKatalogu != null) ZmianaKatalogu(sender, e);
        }

        public delegate void DwukrotneKliknieciePlikuEventHandler(object sender, EventArgs e, string nazwaPliku);
        [
           Category("Katalog"),
           Description("Występuje w przypadku dwukrotnego kliknięcia jednego z plików widocznych na liście.")
        ]
        public event DwukrotneKliknieciePlikuEventHandler DwukrotneKliknieciePliku;
        protected virtual void OnDwukrotneKliknieciePliku(object sender, EventArgs e, string nazwaPliku)
        {
            if (DwukrotneKliknieciePliku != null) DwukrotneKliknieciePliku(this, e, nazwaPliku);
        }
        #endregion        
    }
}
