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


namespace ScanAssistant
{
    public partial class FormMain : Form
    {
        public string sourceDir;
        public List<string> fileNames;
        public string destinationDir;
        public FormMain()
        {
            InitializeComponent();
            comboBoxDPI.SelectedItem = 600;
        }

        private void btnNew_Click(object sender, EventArgs e)
        {
            panelMainWork.BringToFront();
            FormOpenSourceDir opendir = new FormOpenSourceDir();
            opendir.ShowDialog();
            destinationDir = opendir.destinationDir;
            sourceDir = opendir.sourceDir;
            fileNames = opendir.fileNames;

            if (!string.IsNullOrEmpty(sourceDir))
            {
                panelMainWork.Visible = true;
            }
        }

        private void newProjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            panelMainWork.Visible = false;
        }

        private void closeProjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            panelMainWork.Visible = false;
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            panelMainWork.Visible = true;
            panelNewOpenProject.Visible = false;
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (DialogAbout about = new DialogAbout())
            {
                about.ShowDialog();
            }
        }

        private void quitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult quit = MessageBox.Show("Do you want to quit this application?", "Quit?", MessageBoxButtons.YesNo);
            if(quit == DialogResult.Yes)
            {
                Application.Exit();
            }
        }


        private void buttonInitiate_Click(object sender, EventArgs e)
        {
            
            if (Convert.ToInt32(textBoxBlack.Text) >= Convert.ToInt32(textBoxWhite.Text))
            {
                MessageBox.Show("White amount cannot be equal or less than black amount", "Blacker than black", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            else if (Directory.GetFiles(destinationDir).Count() > 0)
            {
                DialogResult dialog = MessageBox.Show("Destination directory contains files, can't continue unless you delete the files", "Delete files in destination directory?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (dialog == DialogResult.Yes)
                {
                    DirectoryInfo di = new DirectoryInfo(destinationDir);
                    foreach (FileInfo file in di.GetFiles())
                    {
                        file.Delete();
                    }
                    progressBarInitiate.Maximum = fileNames.Count();
                    progressBarInitiate.Value = 0;
                    initiate();
                }
            }
            else
            {
                progressBarInitiate.Maximum = fileNames.Count();
                progressBarInitiate.Value = 0;
                initiate();
            }
        }

        // todo make cofigurable default settings
        private void buttonSetDefault_Click(object sender, EventArgs e)
        {
            textBoxBlack.Text = "11";
            textBoxWhite.Text = "86";
        }

        // TODO - external apps should reside with this app
        // Check on startup if required programs exist (perhaps check md5 sum of files?)
        // fix paths
        // cleanup code
        // check for possibility to select/deselect -in app- the usage of one or more cores

        // PRIMARY TODO -> New/Open Screen should change to "Pre Scantailor" and "Post Scantailor"
        // post scantailor -> select working dirs
        // evaluate if saving project settings is needed (atm not needed)

        // Missing stuff yet to add
        // select path for source images, post scantailor
        // make selectable which files should be converted to grayscale - preview pics
        // make selectable which files should be opened with your fav pic editor
        // check during very first startup - mspaint, paint.net, gimp, adobe, make selectable which app should be default pic editor
        // working temp dir needs defined, using %temp%\<generated random dir> ? - delete this after shutting down app.
        // compress 1-bit to g4 fax sourceFile -> %temp% -> sourceFile
        // make pdf
        // sorting output : firstpage -> lastpage only (folded booklet with back/front, 2-3, 4-5 etc) , 
        //                  (fullpage magazine scans) back/front; 2/second-last; third-last/3; 4/fourth-last
        //                  (simplex scanned front to back, back to front) 1, 3, 5 .... 6, 4, 2     
        // generate tablet size version (150dpi)
        // create sha1 + md5 files of output

        // version 2.0
        // add jobs to task manager


        // Step 1 use convert (ImageMagick) to adjust contrast from files in sourceDir to destinationDir
        private void initiate()
        {
            Parallel.ForEach(fileNames, (file) =>
            {
                // Progress bar that doesn't work atm -> 911 @ PET/Dexion
                // Here it only shows progress after jobs are done
                //BeginInvoke((Action)delegate { progressBarInitiate.Refresh(); });
                //BeginInvoke((Action)delegate { progressBarInitiate.Value++; });
                string destinationFile = destinationDir + "\\" + Path.GetFileNameWithoutExtension(file) + ".tif";
                string sourceFile = sourceDir + "\\" + file;
                string fArgument = "\"" + sourceFile + "\" -level " + textBoxBlack.Text + "%," + textBoxWhite.Text + "% \"" + destinationFile + "\"";
                ProcessStartInfo startInfo = new ProcessStartInfo()
                {
                    FileName = "C:\\Program Files\\ImageMagick-6.9.3-Q16\\convert.exe",
                    Arguments = fArgument,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true
                };
                Process p = new Process();
                //p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                p.StartInfo = startInfo;
                p.Start();
                //p.BeginOutputReadLine();
                string output = p.StandardOutput.ReadToEnd();
                //Console.WriteLine(output);
                string err = p.StandardError.ReadToEnd();
                //Console.WriteLine(err);
                
                p.WaitForExit();

                // here the progress shows correctly -make note of invoke/begininvoke- but never finishes
                // 198 test files = only 160-175ish output files.
                // progress bar code is in a trial and error state - unknown what happens if it runs now.
                Invoke(new Action(() => progressBarInitiate.Value++));
                
            });
        }


        // Add metadata to PDF File
        public static void add_meta_to_file(string filename, string outname)
        {
            // Requires PDFTK (server/console)
            ProcessStartInfo startInfo = new ProcessStartInfo()
            {
                FileName = "pdftk.exe",
                Arguments = "\"" + filename + "\"" + " update_info D:\\Retro-Work\\metadata.txt output " + "\"" + outname + "\"",
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardError = true,
                RedirectStandardOutput = true
            };
            Process p = new Process();
            p.StartInfo = startInfo;
            p.Start();
            string output = p.StandardOutput.ReadToEnd();
            string err = p.StandardError.ReadToEnd();
            p.WaitForExit();
        }

        // Add metadata to multiple PDF files - FIXME
        static void add_meta_to_pdfs()
        {
            //var files = Directory.EnumerateFiles("C:\\path", "*.*", SearchOption.AllDirectories)
            // .Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));
            string[] files = Directory.GetFiles("D:\\Retro-Work\\Manual\\New folder\\", "*_recognized.pdf");

            Parallel.ForEach(files, (file) =>
            {
                string outFileName = Path.GetFileNameWithoutExtension(file.Replace("_recognized", ""));
                string outdir = "D:\\Retro-Work\\Manual\\New folder\\ToTorrent\\";

                if (!Directory.Exists(outdir + outFileName))
                {
                    DirectoryInfo di = Directory.CreateDirectory(outdir + outFileName);
                }

                add_meta_to_file(file, outdir + outFileName + ".pdf");
            });
        }

        // Compress 1-Bit files with G4
        static void g4compress_files(string dir)
        {

            // Requires ImageMagick's identify - TODO grab stdout 1-bit vs 8-bit and add to list
            string[] files = Directory.GetFiles(dir, "*.tif");

            // examine if files = 1bit : add to g4 compress list
            Parallel.ForEach(files, (file) =>
            {
                string sourceFile = file;
                string fArgument = "\"" + sourceFile + "\"";
                ProcessStartInfo startInfo = new ProcessStartInfo()
                {
                    FileName = "C:\\Program Files\\ImageMagick-6.9.3-Q16\\identify.exe",
                    Arguments = fArgument,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true
                };
                Process p = new Process();
                p.StartInfo = startInfo;
                p.Start();
                //p.BeginOutputReadLine();
                string output = p.StandardOutput.ReadToEnd();
                string err = p.StandardError.ReadToEnd();
                p.WaitForExit();
            });


            // compress 1-bit files to G4 - TODO use imagemagick instead
            Parallel.ForEach(files, (file) =>
            {
                string filename = Path.GetFileName(file);
                string fArgument = "\"" + file + "\"" + " /tifc=4 /convert=\"" + dir + "\\g4out\\" + filename + "\"";
                ProcessStartInfo startInfo = new ProcessStartInfo()
                {
                    FileName = "c:\\Program Files (x86)\\IrfanView\\i_view32.exe",
                    Arguments = fArgument,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true
                };
                Process p = new Process();
                //p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                p.StartInfo = startInfo;
                p.Start();
                //p.BeginOutputReadLine();
                string output = p.StandardOutput.ReadToEnd();
                Console.WriteLine(output);
                string err = p.StandardError.ReadToEnd();
                Console.WriteLine(err);

                p.WaitForExit();
            });
        }


        // make pdf files from each dir's image files - nested - FIXME this is only used in specific times, make a console app for this?!?
        static void make_pdfs_in_dirs()
        {
            string[] dirs = Directory.GetDirectories("D:\\Retro-Work\\Manual\\New folder\\work\\");

            foreach (string dir in dirs)
            {
                string outdir = dir + "\\pdf";

                if (!Directory.Exists(outdir))
                {
                    DirectoryInfo di = Directory.CreateDirectory(outdir);
                }
                make_pdf(dir);
            }
        }


        // Create a pdf file from working directory when everything else is in place
        static void make_pdf(string dir)
        {
            string[] files = Directory.GetFiles(dir, "*.tif");

            Parallel.ForEach(files, (file) =>
            {
                string filename = Path.GetFileName(file);
                string fArgument = "\"" + file + "\" " + "\"" + dir + "\\pdf\\" + filename + ".pdf\"";
                ProcessStartInfo startInfo = new ProcessStartInfo()
                {
                    FileName = "C:\\Program Files\\ImageMagick-6.9.3-Q16\\convert.exe",
                    Arguments = fArgument,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true
                };
                Process p = new Process();
                p.StartInfo = startInfo;
                p.Start();
                string output = p.StandardOutput.ReadToEnd();
                Console.WriteLine(output);
                string err = p.StandardError.ReadToEnd();
                Console.WriteLine(err);

                p.WaitForExit();
            });

            // TODO make selectable tablet or A4 to add as last page
            string fileName = Path.GetFileName(dir);
            string fArgumentPDF = "\"" + dir + "\\pdf\\*.pdf\" D:\\Retro-Work\\brought_to_you_by_[TABLET].pdf cat output \"" + dir + "\\..\\" + fileName + ".pdf\"";
            ProcessStartInfo startInfo2 = new ProcessStartInfo()
            {
                FileName = "C:\\Program Files (x86)\\PDFtk Server\\bin\\pdftk.exe",
                Arguments = fArgumentPDF,
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardError = true,
                RedirectStandardOutput = true
            };
            Process p2 = new Process();
            //p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            p2.StartInfo = startInfo2;
            p2.Start();
            //p.BeginOutputReadLine();
            string output2 = p2.StandardOutput.ReadToEnd();
            Console.WriteLine(output2);
            string err2 = p2.StandardError.ReadToEnd();
            Console.WriteLine(err2);

            p2.WaitForExit();
        }


        // using transmission BT to create a torrent file from designated dir - TODO config/output dir
        static void create_torrent()
        {
            string comment = "\"From the archives of http://retro-commodore.eu\"";

            string dir = "D:\\Retro-Work\\Manual\\New folder\\ToTorrent";
            string[] files = Directory.GetDirectories(dir);

            Parallel.ForEach(files, (file) =>
            {
                string fileName = Path.GetFileNameWithoutExtension(file);
                string fArgument = "-p -c " + comment + " -t udp://AmigaCity.xyz:6969 -o \"" + dir + "\\" + fileName + ".torrent\" \"" + file + "\"";
                ProcessStartInfo startInfo = new ProcessStartInfo()
                {
                    FileName = "C:\\Program Files\\Transmission\\transmission-create.exe",
                    Arguments = fArgument,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true
                };
                Process p = new Process();
                //p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                p.StartInfo = startInfo;
                p.Start();
                //p.BeginOutputReadLine();
                string output = p.StandardOutput.ReadToEnd();
                Console.WriteLine(output);
                string err = p.StandardError.ReadToEnd();
                Console.WriteLine(err);

                p.WaitForExit();

                File.AppendAllText(file + ".txt", Environment.NewLine + "torrent: " + fileName + ".torrent" + Environment.NewLine);

            });
        }
    }
}
