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

namespace RMDEC
{
    public partial class MVProjectToolset : Form
    {
        public MVProject mvProject;
        public MVProjectToolset(MVProject proj)
        {
            mvProject = proj;
            InitializeComponent();
        }

        private List<string> encFileList = new List<string>();
        private List<string> decFileList = new List<string>();

        private bool encryptedIndexingComplete = false;
        private bool unencryptedIndexingComplete = false;
        private void onIndexThreadComplete()
        {
            if(encryptedIndexingComplete && unencryptedIndexingComplete)
            {
                processingText.Text = "Waiting";
                processingText.BackColor = Color.Red;

                decryptSelected.Enabled = true;
                encryptSelected.Enabled = true;

                makeMV.Enabled = true;
                unmakeMV.Enabled = true;

                processingBar.Style = ProgressBarStyle.Continuous;

                this.Cursor = Cursors.Arrow;
            }
        }
        private void indexFiles()
        {
            processingText.Text = "Indexing";
            processingText.BackColor = Color.Yellow;
            processingBar.Style = ProgressBarStyle.Marquee;
            this.Cursor = Cursors.WaitCursor;

            //Index Encrypted Files
            Thread indexEncryptedFilesThread = new Thread(() =>
            {

                List<string> pngList = new List<string>();
                List<string> oggList = new List<string>();
                List<string> M4AList = new List<string>();

                foreach (string file in Directory.EnumerateFiles(mvProject.FilePath, "*", SearchOption.AllDirectories))
                {


                    string fileExtension = Path.GetExtension(file);

                    switch (fileExtension)
                    {
                        case ".rpgmvp":
                            pngList.Add(file);
                            break;
                        case ".rpgmvo":
                            oggList.Add(file);
                            break;
                        case ".rpgmvm":
                            M4AList.Add(file);
                            break;
                    }


                }

                //add PNG
                foreach (string png in pngList)
                {
                    string relativeName = png.Remove(0, mvProject.FilePath.Length+1);
                    Invoke((Action)delegate
                    {
                        encryptedFileList.Items.Add("[PNG] " + relativeName);
                    });
                    encFileList.Add(png);
                }

                //add OGG
                foreach (string ogg in oggList)
                {
                    string relativeName = ogg.Remove(0, mvProject.FilePath.Length+1);
                    Invoke((Action)delegate
                    {
                        encryptedFileList.Items.Add("[OGG] " + relativeName);
                    });
                    encFileList.Add(ogg);
                }

                //add M4A
                foreach (string M4A in M4AList)
                {
                    string relativeName = M4A.Remove(0, mvProject.FilePath.Length+1);
                    Invoke((Action)delegate
                    {
                        encryptedFileList.Items.Add("[M4A] " + relativeName);
                    });
                    encFileList.Add(M4A);
                }

                Invoke((Action)delegate
                {
                    encryptedIndexingComplete = true;
                    onIndexThreadComplete();
                });
                
            });
            indexEncryptedFilesThread.Start();

            //Index Unencrypted Files
            Thread indexUnencryptedFilesThread = new Thread(() =>
            {

                List<string> pngList = new List<string>();
                List<string> oggList = new List<string>();
                List<string> M4AList = new List<string>();

                foreach (string file in Directory.EnumerateFiles(mvProject.FilePath, "*", SearchOption.AllDirectories))
                {

                    string fileExtension = Path.GetExtension(file);

                    switch (fileExtension)
                    {
                        case ".png":
                            pngList.Add(file);
                            break;
                        case ".ogg":
                            oggList.Add(file);
                            break;
                        case ".M4A":
                            M4AList.Add(file);
                            break;
                    }


                }

                //add PNG
                foreach (string png in pngList)
                {
                    string relativeName = png.Remove(0, mvProject.FilePath.Length+1);
                    Invoke((Action)delegate
                    {
                        decryptedFileList.Items.Add("[PNG] " + relativeName);
                    });
                    decFileList.Add(png);
                }

                //add OGG
                foreach (string ogg in oggList)
                {
                    string relativeName = ogg.Remove(0, mvProject.FilePath.Length+1);
                    Invoke((Action)delegate
                    {
                        decryptedFileList.Items.Add("[OGG] " + relativeName);
                    });
                    decFileList.Add(ogg);
                }

                //add M4A
                foreach (string M4A in M4AList)
                {
                    string relativeName = M4A.Remove(0, mvProject.FilePath.Length+1);
                    Invoke((Action)delegate
                    {
                        decryptedFileList.Items.Add("[M4A] " + relativeName);
                    });
                    decFileList.Add(M4A);
                }

                Invoke((Action)delegate
                {
                    unencryptedIndexingComplete = true;
                    onIndexThreadComplete();
                });
            });
            indexUnencryptedFilesThread.Start();


        }
        private void MVProjectToolset_Load(object sender, EventArgs e)
        {
            this.Text = "RMDec - RPG Maker MV - " + mvProject.GameTitle + " - " + mvProject.FilePath;
            indexFiles();
        }

        private void encryptSelected_Click(object sender, EventArgs e)
        {

        }

        private void decryptSelected_Click(object sender, EventArgs e)
        {
            SelectedIndexCollection itemList = encryptedFileList.SelectedIndices;
            int itemCount = itemList.Count;

            if (itemCount < 1)
            {
                return;
            }

            int[] selectedIndexes = new int[itemCount];
            int item = 0;

            itemList.CopyTo(selectedIndexes, 0);

            processingBar.Style = ProgressBarStyle.Continuous;
            processingBar.Maximum = itemCount;

            processingText.BackColor = Color.Yellow;

            encryptSelected.Enabled = false;
            decryptSelected.Enabled = false;

            Thread decryptFilesThread = new Thread(() =>
            {
                int i = 1;
                int total = itemCount;
                do
                {

                    Invoke((Action)delegate
                    {

                        itemCount = itemList.Count;
                        item = itemList[0];

                        processingText.Text = "Decrypting " + i.ToString() + "/" + total.ToString();
                    });



                    string encryptedFile = encFileList[item];
                    string extension = Path.GetExtension(encryptedFile);
                    string newExtension = "";

                    switch (extension)
                    {
                        case ".rpgmvp":
                            newExtension = ".png";
                            break;
                        case ".rpgmvo":
                            newExtension = "ogg";
                            break;
                        case ".rpgmvm":
                            newExtension = ".m4a";
                            break;

                    }

                    string decryptedFile = Path.ChangeExtension(encryptedFile, newExtension);

                    FileStream Encrypted = File.OpenRead(encryptedFile);
                    FileStream Decrypted = File.OpenWrite(decryptedFile);

                    mvProject.DecryptFile(Encrypted, Decrypted);

                    Encrypted.Close();
                    Decrypted.Close();

                    File.Delete(encryptedFile);

                    Invoke((Action)delegate
                    {
                        string entry = encryptedFileList.Items[item].ToString();
                        string decryptedEntry = Path.ChangeExtension(entry, newExtension);
                        decryptedFileList.Items.Add(decryptedEntry);
                        decFileList.Add(decryptedFile);

                        encryptedFileList.Items.Remove(entry);
                        encFileList.RemoveAt(item);

                        processingBar.Value = i;
                    });

                    i++;
                } while (itemCount > 1);

                Invoke((Action)delegate
                {
                    encryptSelected.Enabled = true;
                    decryptSelected.Enabled = true;
                    processingText.BackColor = Color.Green;
                    processingText.Text = "Decrypted " + total.ToString() + " files!";
                });
            });

            

            decryptFilesThread.Start();



            
        }


    }
}
