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;
using System.Net;
using System.Drawing.Printing;
using System.Deployment.Application;

namespace PhotoViewer
{
    enum WebRequestMethod
    {
        MakeDirectory,
        DownloadFile,
        ListDirectoryDetails,
        RemoveDirectory,
        DeleteFile
    }

    public partial class Form1 : Form
    {
        //---stałe ikon---
        const int ico_OPEN = 0;
        const int ico_CLOSE = 1;
        const int ico_PHOTO = 2;

        //---zmienne czcionek---
        Font f_title;
        Font f_body;

        //---licznik stron---
        int pagecounter;

        //---zmienna typu PrintDocument---
        PrintDocument printDoc;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            printDoc = new PrintDocument()
            {
                DocumentName = "Drukowanie z programu Przeglądarka zdjęć"
            };
            printDoc.BeginPrint += new PrintEventHandler(printDoc_BeginPrint);
            printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage);
            printDoc.EndPrint += new PrintEventHandler(printDoc_EndPrint);

            try
            {
                //---ładowanie wartości ustawień aplikacji
                // do kontrolek typu TextBox---
                txtFTPServer.Text = Properties.Settings.Default.FTP_SERVER;
                txtUserName.Text = Properties.Settings.Default.UserName;
                txtPassword.Text = Properties.Settings.Default.Password;

                //-—-tworzenie głównego węzła dla kontrolki typu TreeView—--
                TreeNode node = new TreeNode();
                node.ImageIndex = ico_CLOSE;
                node.SelectedImageIndex = ico_OPEN;
                node.Text = @"/";

                //---dodawanie głównego węzła do kontrolki---
                TreeView1.Nodes.Add(node);

                //-—-dodawania pustego węzła podrzędnego—--
                node.Nodes.Add("");

                //---zaznaczenie węzła głównego---
                TreeView1.SelectedNode = node;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        void printDoc_EndPrint(object sender, PrintEventArgs e)
        {
            //---zwalnianie czcionek---
            f_title = null;
            f_body = null;
        }

        void printDoc_PrintPage(object sender, PrintPageEventArgs e)
        {
            Graphics g = e.Graphics;

            //---rysowanie nagłówka---
            g.DrawString(TreeView1.SelectedNode.Text,
                f_title, Brushes.Black, 20, 30);

            //---rysowanie obramowania...---
            Rectangle border =
                new Rectangle(10, 10, PictureBox1.Width + 20, PictureBox1.Height + 60);

            //---...za pomocą grubego pióra---
            Pen thickPen = new Pen(Color.Black, 3);
            g.DrawRectangle(thickPen, border);

            //---rysowanie obrazka---
            if (PictureBox1.Image != null)
            {
                g.DrawImage(PictureBox1.Image, 20, 60,
                PictureBox1.Size.Width,
                PictureBox1.Size.Height);
            }

            //---rysowanie licznika stron---
            g.DrawString("Strona " + pagecounter,
               f_body, Brushes.Black,
               20, 420);

            //---powiększanie wartości licznika stron---
            pagecounter += 1;

            //---sprawdzenie, czy są jeszcze strony do wydrukowania---
            if (pagecounter <= int.Parse(txtTo.Text))
                e.HasMorePages = true;
            else
                e.HasMorePages = false;
        }

        void printDoc_BeginPrint(object sender, PrintEventArgs e)
        {
            //---inicjowanie licznika stron---
            pagecounter = int.Parse(txtFrom.Text);

            //---inicjowanie czcionek---
            f_title = new Font("Arial", 16, FontStyle.Bold);
            f_body = new Font("Times New Roman", 10);
        }

        //---tworzy zawartość katalogu w kontrolce TreeView---
        private void BuildDirectory(TreeNode ParentNode)
        {
            string[] listing = GetDirectoryListing(
                Properties.Settings.Default.FTP_SERVER +
                ParentNode.FullPath);
            foreach (string line in listing)
            {
                if (line == String.Empty) break;

                TreeNode node = new TreeNode();
                if (line.Substring(24, 5) == "<DIR>")
                {
                    //---to jest katalog; tworzenie nowego węzła---
                    node.Text = line.Substring(39);
                    node.ImageIndex = ico_CLOSE;
                    node.SelectedImageIndex = ico_OPEN;

                    //---dodawanie pustego węzła podrzędnego---
                    node.Nodes.Add("");
                    ParentNode.Nodes.Add(node);
                }
                else
                {
                    //---to jest zwykły plik; tworzenie nowego węzła opisującego plik---
                    node.Text = line.Substring(39);
                    node.ImageIndex = ico_PHOTO;
                    node.SelectedImageIndex = ico_PHOTO;
                    ParentNode.Nodes.Add(node);
                }
            }
        }

        private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            //---pierwszy znak "/" jest zawsze ignorowany---
            string FullPath =
               Properties.Settings.Default.FTP_SERVER +
               e.Node.FullPath.Substring(1).Replace("\r", "");

            //---wyświetlanie aktualnie wybranego folderu---
            if (e.Node.ImageIndex != ico_PHOTO)
            {
                ToolStripStatusLabel1.Text = FullPath;
                return;
            }

            //---pobieranie obrazu---
            DownloadImage(FullPath);
        }

        private void TreeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            //---jeżeli węzeł jest liściem ,to wyjdź z procedury---
            if (e.Node.ImageIndex == ico_PHOTO) return;

            //---usunięcie pustego węzła i wyświetlenie podkatalogów i plików---
            try
            {
                //---usunięcie wszystkich węzłów i...---
                e.Node.Nodes.Clear();

                //---utworzenie ich od nowa---
                BuildDirectory(e.Node);
            }
            catch (Exception ex)
            {
                ToolStripStatusLabel1.Text = ex.ToString();
            }

            //---zmiana ikony węzła na ikonę otwartego folderu---
            if (e.Node.GetNodeCount(false) > 0)
            {
                e.Node.ImageIndex = ico_CLOSE;
                e.Node.SelectedImageIndex = ico_OPEN;
            }
        }

        //---pobiera obrazek z serwera FTP---
        private void DownloadImage(string path)
        {
            try
            {
                ToolStripStatusLabel1.Text = "Pobieranie obrazka..." + path;
                Application.DoEvents();

                //---pobieranie obrazka---
                FtpWebResponse FTPResp =
                    PerformWebRequest(path,
                    WebRequestMethod.DownloadFile);

                //---pobranie strumienia przechowującego obrazek---
                Stream ftpRespStream = FTPResp.GetResponseStream();

                //---wyświetlenie obrazka---
                PictureBox1.Image = Image.FromStream(ftpRespStream);
                FTPResp.Close();

                ToolStripStatusLabel1.Text =
                    "Pobieranie obrazka...gotowe (" + path + ")";
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        //---pobiera listę plików i katalogów z zwraca ją w postaci tablicy ciągów znaków---
        private string[] GetDirectoryListing(string path)
        {
            try
            {
                //---pobieranie listy katalogów---
                FtpWebResponse FTPResp = PerformWebRequest(
                    path, WebRequestMethod.ListDirectoryDetails);

                //---pobieranie strumienia przechowującego listę katalogów---
                Stream ftpRespStream = FTPResp.GetResponseStream();
                StreamReader reader =
                    new StreamReader(ftpRespStream, System.Text.Encoding.UTF8);

                //---przekształcenie wyniku w tablicę ciągów znaków---
                string[] result = reader.ReadToEnd().Split(
                    Environment.NewLine.ToCharArray(),
                    StringSplitOptions.RemoveEmptyEntries);
                FTPResp.Close();
                return result;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return null;
            }
        }

        //---tworzenie nowego katalogu---
        private void btnCreateFolder_Click(object sender, EventArgs e)
        {
            //---sprawdzić, czy użytkownik zaznaczył już katalog---
            if (TreeView1.SelectedNode.ImageIndex == ico_PHOTO)
            {
                MessageBox.Show("Proszę zaznaczyć katalog na liście.");
                return;
            }

            try
            {
                //---tworzenie pełnej ścieżki do katalogu, który ma zostać utworzony---
                string folder = Properties.Settings.Default.FTP_SERVER +
                   TreeView1.SelectedNode.FullPath.Substring(1).Replace
                   ("\r", "") + @"/" + txtNewFolderName.Text;

                //---tworzenie nowego katalogu---
                FtpWebResponse ftpResp =
                    PerformWebRequest(folder, WebRequestMethod.MakeDirectory);
                ftpResp.Close();


                //---odświeżenie utworzonego właśnie katalogu---
                RefreshCurrentFolder();

                //---aktualizacja paska statusu---
                ToolStripStatusLabel1.Text = ftpResp.StatusDescription.Replace("\r\n", string.Empty);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void btnUploadPhotos_Click(object sender, EventArgs e)
        {
            //---sprawdzenie, czy użytkownik wybrał katalog---
            if (TreeView1.SelectedNode.ImageIndex == ico_PHOTO)
            {
                MessageBox.Show("Proszę zaznaczyć katalog, w którym mają zostać umieszoczne zdjęcia.");
                return;
            }

            OpenFileDialog openFileDialog1 = new OpenFileDialog()
            {
                Filter = "Pliki jpg (*.jpg)|*.jpg",
                FilterIndex = 2,
                RestoreDirectory = true,
                Multiselect = true
            };

            //---definiowanie pełnej ścieżki do katalogu---
            string currentSelectedPath =
               Properties.Settings.Default.FTP_SERVER + TreeView1.SelectedNode.FullPath.Substring(1).Replace("\r", "");

            //---proszenie użytkownika o wybranie zdjęć---
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                //---pojedyncze przesyłanie zdjęć---
                for (int i = 0; i <= openFileDialog1.FileNames.Length - 1; i++)
                {
                    UploadImage(currentSelectedPath + "/" +
                       openFileDialog1.FileNames[i].Substring(
                       openFileDialog1.FileNames[i].LastIndexOf(@"\") + 1),
                       openFileDialog1.FileNames[i]);
                }
            }

            //---odświeżenie katalogu, tak żeby pojawiły się przesłane zdjęcia---
            RefreshCurrentFolder();
        }

        private void RefreshCurrentFolder()
        {
            //---czyszczenie wszystkich węzłów i...---
            TreeView1.SelectedNode.Nodes.Clear();

            //---tworzenie ich na nowo---
            BuildDirectory(TreeView1.SelectedNode);
        }

        //---przesyłanie zdjęcia na serwer FTP---
        private void UploadImage(string path, string filename)
        {
            try
            {
                WebClient client = new WebClient();
                client.Credentials = new NetworkCredential(Properties.Settings.Default.UserName, Properties.Settings.Default.Password);

                //---przesyłanie pliku zdjęcia---
                client.UploadFile(path, filename);

                //---aktualizacja paska statusu---
                ToolStripStatusLabel1.Text = filename + " został przesłany!";
                //Application.DoEvents();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
        
        //---usuwanie katalogu---
        private void btnRemoveFolder_Click(object sender, EventArgs e)
        {
            if (TreeView1.SelectedNode.ImageIndex == ico_PHOTO)
            {
                MessageBox.Show("Proszę zaznaczyć katalog do usunięcia.");
                return;
            }

            try
            {
                string FullPath =
                    Properties.Settings.Default.FTP_SERVER + TreeView1.SelectedNode.
                    FullPath.Substring(1).Replace("\r", "");

                //---usuwanie katalogu---
                FtpWebResponse ftpResp =
                    PerformWebRequest(FullPath, WebRequestMethod.RemoveDirectory);

                //---usuwanie aktualnego węzła---
                TreeView1.SelectedNode.Remove();

                //---aktualizowanie paska statusu---
                ToolStripStatusLabel1.Text = ftpResp.StatusDescription.Replace("\r\n", string.Empty);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void btnDeletePhoto_Click(object sender, EventArgs e)
        {
            if (TreeView1.SelectedNode.ImageIndex != ico_PHOTO)
            {
                MessageBox.Show("Proszę zaznaczyć zdjęcie do susunięcia.");
                return;
            }

            try
            {
                string FullPath = Properties.Settings.Default.FTP_SERVER +
                    TreeView1.SelectedNode.FullPath.Substring(1).Replace("\r", "");

                //---usuwanie zdjęcia---
                FtpWebResponse ftpResp =
                    PerformWebRequest(FullPath, WebRequestMethod.DeleteFile);

                //---usuwanie aktualnego węzła---
                TreeView1.SelectedNode.Remove();

                //---aktualizacja paska statusu---
                ToolStripStatusLabel1.Text = ftpResp.StatusDescription.Replace("\r\n", string.Empty);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private FtpWebResponse PerformWebRequest(string path, WebRequestMethod method)
        {
            //---zmiana wskaźnika myszy na klepsydrę---
            Cursor.Current = Cursors.WaitCursor;

            FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(path);
            switch (method)
            {
                case WebRequestMethod.DeleteFile:
                    ftpReq.Method = WebRequestMethods.Ftp.DeleteFile;
                    break;
                case WebRequestMethod.DownloadFile:
                    ftpReq.Method = WebRequestMethods.Ftp.DownloadFile;
                    break;
                case WebRequestMethod.ListDirectoryDetails:
                    ftpReq.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                    break;
                case WebRequestMethod.MakeDirectory:
                    ftpReq.Method = WebRequestMethods.Ftp.MakeDirectory;
                    break;
                case WebRequestMethod.RemoveDirectory:
                    ftpReq.Method = WebRequestMethods.Ftp.RemoveDirectory;
                    break;
            }
            ftpReq.Credentials = new NetworkCredential(
                Properties.Settings.Default.UserName,
                Properties.Settings.Default.Password);

            FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse();

            //---przywrócenie domyślnego wskaźnika myszy---
            Cursor.Current = Cursors.Default;
            return ftpResp;
        }

        private void txtFTPServer_Leave(object sender, EventArgs e)
        {
            //---zapisywanie wartości kontrolek typu TextBox
            // do ustawień aplikacji ---
            Properties.Settings.Default.FTP_SERVER = txtFTPServer.Text;
            Properties.Settings.Default.UserName = txtUserName.Text;
            Properties.Settings.Default.Password = txtPassword.Text;
            Properties.Settings.Default.Save();
        }

        private void btnPrint_Click(object sender, EventArgs e)
        {
            //---użytkownik może wybrać drukarkę---
            PrintDialog pd = new PrintDialog()
            {
                Document = printDoc,
                AllowSomePages = true
            };

            DialogResult result = pd.ShowDialog();
            if (result == DialogResult.OK)
                printDoc.Print();
        }

        private void btnPreview_Click(object sender, EventArgs e)
        {
            //---wyświetlenie podglądu---
            PrintPreviewDialog dlg = new PrintPreviewDialog()
            {
                Document = printDoc
            };
            dlg.ShowDialog();
        }

        private void btnUpdate_Click(object sender, EventArgs e)
        {
            //---sprawdzenie, czy aplikacja obsługiwana jest w systemie ClickOnce---
            if (ApplicationDeployment.IsNetworkDeployed)
            {
                //---pobieranie egzemplarza instalacji---
                ApplicationDeployment deployment =
                    ApplicationDeployment.CurrentDeployment;

                //---poszukiwanie aktualizacji---
                if (deployment.CheckForUpdate())
                {
                    DialogResult response =
                        MessageBox.Show(("Dostępna jest nowsza " +
                        "wersja aplikacji. " +
                        "Chcesz wykonać aktualizację?"),
                        ("Aktualizacja aplikacji"),
                        MessageBoxButtons.YesNo);

                    //---jeżeli użytkownik chce aktualizować---
                    if (response == DialogResult.Yes)
                    {
                        Cursor.Current = Cursors.WaitCursor;

                        //---aktualizowanie aplikacji---
                        deployment.Update();

                        //---konieczne jest ponowne uruchomienie aplikacji---
                        MessageBox.Show("Aktualizacja zakończona. Konieczne jest ponowne uruchomienie aplikacji.",
                           ("Aktualizacja zakończona"), MessageBoxButtons.OK, MessageBoxIcon.Information);

                        //---ponowne uruchomienie aplikacji---
                        Application.Restart();
                    }
                }
                else
                {
                    //---aplikacja jest aktualna---
                    MessageBox.Show(("Aplikacja nie wymaga aktualizacji."), "Aktualizacja",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else
            {
                //---aplikacja nie została zainstalowana przez technologię ClickOnce---
                MessageBox.Show(("Aplikacja nie została zainstalowana za pomocą " +
                    "technologii ClickOnce"),
                   ("Brak aktualizacji"),
                   MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

    }
}

