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


namespace SoundBoard
{
    public partial class formMain : Form, IMessageFilter
    {
        private const int WM_KEYDOWN = 0x100;
        public WMPLib.WindowsMediaPlayer Player = new WMPLib.WindowsMediaPlayer();
        public Random randomNum = new Random();
        public ListView listViewEntity = new ListView();
        public string _workingDirectory = Path.GetDirectoryName(Application.ExecutablePath);
        public string[] _soundFiles;
        public string[] _soundDirectories;

        public formMain()
        {
            InitializeComponent();
        }

        private void formMain_Load(object sender, EventArgs e)
        {
            _soundFiles = Directory.GetFiles(_workingDirectory);
            //Build the UI, foreach directory create one TabPage and one ListView object
            foreach (string sound in _soundFiles)
            {
                CreateUITabs("Working Directory", _workingDirectory);
            }
            _soundDirectories = Directory.GetDirectories(_workingDirectory, "*", SearchOption.TopDirectoryOnly);
            foreach (string sounds in _soundDirectories)
            {
                CreateUITabs(Path.GetFileName(sounds), sounds);
            }

            Application.AddMessageFilter(this);
            fileSystemWatcherMain.Path = _workingDirectory; //watch in the application's working directory
            fileSystemWatcherMain.IncludeSubdirectories = true; //and watch in the subfolders for changes, but only one layer down from the app's directory
            fileSystemWatcherMain.Created += new FileSystemEventHandler(fileSystemUpdateDetected); //file or folder created
            fileSystemWatcherMain.Deleted += new FileSystemEventHandler(fileSystemUpdateDetected); //file or folder moved or deleted
            fileSystemWatcherMain.Renamed += new RenamedEventHandler(fileSystemUpdateDetected); //for any file changes like file extension changes
            soundboardTabControl.SelectedIndexChanged += new EventHandler(CheckForDisabledListBox); //disables or enables the Show on Disk file menu object
            Player.PlayStateChange += new WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(WMP_PlayStateChange); //eventhandler for the playstate of the Player object
            //check to see if the listView is empty on form load
            if (soundboardTabControl.SelectedTab.Controls[0].Enabled == true)
            {
                mainMenuFileShowOnDisk.Enabled = true;
                btnRandom.Enabled = true;
            }
            else
            {
                mainMenuFileShowOnDisk.Enabled = false;
                btnRandom.Enabled = false;
            }
            soundboardTabControl.Select();
        }

        private void WMP_PlayStateChange(int newState)
        {
            //check to see if the random play functions are running
            if (btnRandom.Enabled == false)
            {
                if (Player.playState == WMPLib.WMPPlayState.wmppsTransitioning)
                {
                    //Player is transitioning, so keep the controls disabled
                    btnRandom.Enabled = false;
                    loopSelectedSoundCheckBox.Enabled = false;
                }
                else if (Player.playState == WMPLib.WMPPlayState.wmppsPlaying)
                {
                    //player is still playing the random playlist, keep the controls disbaled
                    btnRandom.Enabled = false;
                    loopSelectedSoundCheckBox.Enabled = false;
                }
                else if (Player.playState == WMPLib.WMPPlayState.wmppsReady)
                {
                    //renable the controls, the Random functions are done
                    //first check to see if the loop checkBox is checked, if so set the player to "loop"
                    if (soundboardTabControl.SelectedTab.Controls[0].Enabled == true)
                    {
                        btnRandom.Enabled = true;
                    }
                    if (loopSelectedSoundCheckBox.Checked == true)
                    {
                        Player.settings.setMode("loop", true);
                    }
                    loopSelectedSoundCheckBox.Enabled = true;
                }
            }
        }

        private void fileSystemUpdateDetected(object sender, FileSystemEventArgs e)
        {
            //perform the UI refresh operation
            RefreshUIControls();
        }

        private void CheckForDisabledListBox(object sender, EventArgs e)
        {
            try
            {
                listViewEntity = (ListView)soundboardTabControl.SelectedTab.Controls[0];
            }
            catch (Exception spam)
            {
                return;
            }

            if (listViewEntity.Enabled == false)
            {
                mainMenuFileShowOnDisk.Enabled = false;
                btnRandom.Enabled = false;
            }
            else
            {
                mainMenuFileShowOnDisk.Enabled = true;
                btnRandom.Enabled = true;
            }
        }

        private void RefreshUIControls()
        {
            _workingDirectory = Path.GetDirectoryName(Application.ExecutablePath);
            _soundDirectories = Directory.GetDirectories(_workingDirectory);
            
            foreach (TabPage tabPage in soundboardTabControl.TabPages)
            {
                foreach (ListView listView in tabPage.Controls)
                {
                    listView.Dispose();
                }
                tabPage.Dispose();
            }

            foreach (string sounds in _soundFiles)
            {
                CreateUITabs("Working Directory", _workingDirectory);
            }
            foreach (string files in _soundDirectories)
            {
                CreateUITabs(Path.GetFileName(files), files);
            }
            //check to see if the listView is empty
            if (soundboardTabControl.SelectedTab.Controls[0].Enabled == true)
            {
                mainMenuFileShowOnDisk.Enabled = true;
                btnRandom.Enabled = true;
            }
            else
            {
                mainMenuFileShowOnDisk.Enabled = false;
                btnRandom.Enabled = false;
            }
        }

        private void CreateUITabs(string tabName, string directoryPath)
        {
            //Add tabs dynamically
            int soundControlHeight = soundboardTabControl.Height;
            int soundControlWidth = soundboardTabControl.Width;
            string[] directoryFiles; //Files in the target directory
            TabPage tab = new TabPage();
            ListView localListView = new ListView();
            string[] columnNames = new string[2]; //Perhaps include a compatibility column to flag files that cause errors?
            ListViewItem listItemObject;

            if (soundboardTabControl.Controls.ContainsKey(tabName.Replace(" ", "") + "Tab"))
            {

            }
            else
            {   
                //Construct the TabPage and its properties
                tab.Text = tabName; //Display the folder's full name to the user
                tab.Name = tabName.Replace(" ", "") + "Tab"; //create a legal name for the tab's (name) property
                tab.Height = soundControlHeight;
                tab.Height = soundControlWidth;
                soundboardTabControl.Controls.Add(tab);

                //Construct the ListView and its properties
                localListView.Height = soundControlHeight - 25;
                localListView.Width = soundControlWidth - 5;
                localListView.Name = tabName.Replace(" ", "") + "ListView";
                localListView.FullRowSelect = true;
                localListView.MultiSelect = false;
                localListView.GridLines = true;
                localListView.View = View.Details;
                localListView.Activation = ItemActivation.OneClick;
                localListView.TabStop = false;
                tab.Controls.Add(localListView);
                localListView.Columns.Add("File Name", 340, HorizontalAlignment.Left);
                localListView.Columns.Add("File Ext", 50, HorizontalAlignment.Left);
                localListView.ItemActivate += new EventHandler((sender, e) => ListViewOnLeftClick(sender, e, localListView));
            }

            directoryFiles = Directory.GetFiles(Path.GetFullPath(directoryPath));

            foreach (string file in directoryFiles)
            {
                switch (Path.GetExtension(file).ToLower())
                {
                    //Only include sound files in the ListView
                    case ".mp3":
                    case ".wav":
                        columnNames[0] = Path.GetFileNameWithoutExtension(file);
                        columnNames[1] = Path.GetExtension(file);
                        listItemObject = new ListViewItem(columnNames);
                        localListView.Items.Add(listItemObject);
                        break;
                    default:
                        break;
                }
            }

            if (localListView.Items.Count == 0)
            {
                if (tab.Name == "WorkingDirectoryTab")
                {
                    localListView.Items.Add("No sound files detected in the application's working directory.");
                }
                else
                {
                    localListView.Items.Add("No sound files detected in the " + tabName + " directory");
                }
                
                localListView.Enabled = false;
                if (soundboardTabControl.SelectedIndex == 0)
                {
                    mainMenuFileShowOnDisk.Enabled = false;
                    btnRandom.Enabled = false;
                }
            }
        }

        private void ListViewOnLeftClick(object sender, EventArgs e, ListView listView)
        {
            if (btnRandom.Enabled == false)
            {
                //If the btnRandom button is disabled that means a randomise function is running, so don't interupt it
                return;
            }
            string fileName;
            string fileExt;
            string fileLocation;

            fileName = listView.SelectedItems[0].SubItems[0].Text;
            fileExt = listView.SelectedItems[0].SubItems[1].Text;

            if (soundboardTabControl.SelectedIndex == 0)
            {
                if (File.Exists(_workingDirectory + "\\" + fileName + fileExt))
                {
                    fileLocation = _workingDirectory + "\\" + fileName + fileExt;
                }
                else
                {
                    return;
                }
            }
            else
            {
                if (File.Exists(_workingDirectory + "\\" + soundboardTabControl.SelectedTab.Text + "\\" + fileName + fileExt))
                {
                    fileLocation = _workingDirectory + "\\" + soundboardTabControl.SelectedTab.Text + "\\" + fileName + fileExt;
                }
                else
                {
                    return;
                }
            }
            PlaySoundFile(fileLocation);
        }

        private void btnRandom_Click(object sender, EventArgs e)
        {
            int iterations = (int)randomIterationNumericUpDown.Value;
            listViewEntity = (ListView)soundboardTabControl.SelectedTab.Controls[0];
            Player.currentPlaylist.clear();

            //DOuble check to see if the ListView has any items that can be played
            if (listViewEntity.Enabled == false)
            {
                //the ListView disabled and therefore contains no sounds, so return
                return;
            }
            //disable the Random Button and the loop checkbox
            btnRandom.Enabled = false;
            loopSelectedSoundCheckBox.Enabled = false;

            if (mainMenuPlayAll.Checked == true)
            {
                playRandomSoundBothColumns(iterations);
                if (soundboardTabControl.SelectedTab.Controls[0].Enabled == true)
                {
                    btnRandom.Enabled = true;
                }
                loopSelectedSoundCheckBox.Enabled = true;
                return;
            }

            for (int i = 0; i < iterations; i++)
            {
                string fileLocation = "";
                string fileExt;
                string fileName;
                //Check to see if the selected tab is the working directory's tab
                if (soundboardTabControl.SelectedIndex == 0)
                {
                    listViewEntity.Items[randomNum.Next(listViewEntity.Items.Count)].Selected = true;
                    fileName = listViewEntity.SelectedItems[0].SubItems[0].Text;
                    fileExt = listViewEntity.SelectedItems[0].SubItems[1].Text;

                    if (File.Exists(_workingDirectory + "\\" + fileName + fileExt))
                    {
                        fileLocation = _workingDirectory + "\\" + fileName + fileExt;
                    }
                    else
                    {
                        MessageBox.Show("The file couldn't be found.", "File Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        if (soundboardTabControl.SelectedTab.Controls[0].Enabled == true)
                        {
                            btnRandom.Enabled = true;
                        }
                        loopSelectedSoundCheckBox.Enabled = true;
                        Player.currentPlaylist.clear();
                        return;
                    }
                }
                else
                {
                    listViewEntity.Items[randomNum.Next(listViewEntity.Items.Count)].Selected = true;
                    fileName = listViewEntity.SelectedItems[0].SubItems[0].Text;
                    fileExt = listViewEntity.SelectedItems[0].SubItems[1].Text;

                    if (File.Exists(_workingDirectory + "\\" + soundboardTabControl.SelectedTab.Text + "\\" + fileName + fileExt))
                    {
                        fileLocation = _workingDirectory + "\\" + soundboardTabControl.SelectedTab.Text + "\\" + fileName + fileExt;
                    }
                    else
                    {
                        MessageBox.Show(_workingDirectory + "\\" + soundboardTabControl.SelectedTab.Text + "\\" + fileName + fileExt, "Not Found");
                        if (soundboardTabControl.SelectedTab.Controls[0].Enabled == true)
                        {
                            btnRandom.Enabled = true;
                        }
                        loopSelectedSoundCheckBox.Enabled = true;
                        Player.currentPlaylist.clear();
                        return;                        
                    }
                }
                //load the player with the randomly chosen sounds
                enumeratePlayerPlayList(fileLocation);
            }
            //prepare the Player object and play the playlist
            btnRandom.Enabled = false;
            Player.settings.setMode("loop", false);
            PlayPlayList();
        }

        private void PlaySoundFile(string fileLocation)
        {
            //Set the file to be played's location
            Player.URL = fileLocation;
            
            //Attempt to play the file
            try
            {
                Player.controls.play();
            }
            catch (InvalidOperationException Ex)
            {
                MessageBox.Show("The file couldn't be played.", "Invalid Sound File", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void loopSelectedSoundCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (loopSelectedSoundCheckBox.Checked == true)
            {
                Player.settings.setMode("loop", true);
            }
            else
            {
                Player.settings.setMode("loop", false);
            }
        }

        private void playRandomSoundBothColumns(int iterations)
        {
            int tempRandomNumber;
            string fileLocation = "";
            string fileName;
            string fileExt;
            listViewEntity = (ListView)soundboardTabControl.SelectedTab.Controls[0];

            for (int i = 0; i <= iterations; i++)
            {
                tempRandomNumber = randomNum.Next(0, soundboardTabControl.TabCount);

                if (soundboardTabControl.TabPages[tempRandomNumber].Controls[0].Enabled == true)
                {
                    soundboardTabControl.SelectedIndex = tempRandomNumber;
                    if (soundboardTabControl.SelectedIndex == 0)
                    {
                        listViewEntity.Items[randomNum.Next(listViewEntity.Items.Count)].Selected = true;
                        fileName = listViewEntity.SelectedItems[0].SubItems[0].Text;
                        fileExt = listViewEntity.SelectedItems[0].SubItems[1].Text;

                        if (File.Exists(_workingDirectory + "\\" + fileName + fileExt))
                        {
                            fileLocation = _workingDirectory + "\\" + fileName + fileExt;
                        }
                        else
                        {
                            return;
                        }
                    }
                    else
                    {
                        listViewEntity.Items[randomNum.Next(listViewEntity.Items.Count)].Selected = true;
                        fileName = listViewEntity.SelectedItems[0].SubItems[0].Text;
                        fileExt = listViewEntity.SelectedItems[0].SubItems[1].Text;

                        if (File.Exists(_workingDirectory + "\\" + soundboardTabControl.SelectedTab.Text + "\\" + fileName + fileExt))
                        {
                            fileLocation = _workingDirectory + "\\" + soundboardTabControl.SelectedTab.Text + "\\" + fileName + fileExt;
                        }
                        else
                        {
                            return;
                        }
                    }
                    enumeratePlayerPlayList(fileLocation);
                }
                else
                {
                    playRandomSoundBothColumns(iterations - i);
                }
            }
            PlayPlayList();
        }

        private void mainMenuFileShowOnDisk_Click(object sender, EventArgs e)
        {
            listViewEntity = (ListView)soundboardTabControl.SelectedTab.Controls[0];
            string fileName;
            string fileExt;

            fileName = listViewEntity.SelectedItems[0].SubItems[0].Text;
            fileExt = listViewEntity.SelectedItems[0].SubItems[1].Text;

            if (soundboardTabControl.SelectedIndex == 0)
            {
                if (File.Exists(_workingDirectory + "\\" + fileName + fileExt))
                {
                    Process.Start("explorer.exe", "/select, \"" + _workingDirectory + "\\" + fileName + fileExt + "\"");
                }
            }
            else
            {
                if (File.Exists(_workingDirectory + "\\" + soundboardTabControl.SelectedTab.Text + "\\" + fileName + fileExt))
                {
                    Process.Start("explorer.exe", "/select, \"" + _workingDirectory + "\\" + soundboardTabControl.SelectedTab.Text + "\\" + fileName + fileExt + "\"");
                }
            }
        }

        private void mainMenuHelpAbout_Click(object sender, EventArgs e)
        {
            aboutForm aboutDialogForm = new aboutForm();
            aboutDialogForm.ShowDialog();
            aboutDialogForm.Dispose();
        }

        private void mainMenuFileExit_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void enumeratePlayerPlayList(string fileLocation)
        {
            WMPLib.IWMPMedia playList = Player.newMedia(fileLocation);
            Player.currentPlaylist.appendItem(playList);
        }

        private void PlayPlayList()
        {
            Player.controls.play();
        }
        //Handles all messages being sent to controls
        public bool PreFilterMessage(ref Message m)
        {
            Keys keyCode = (Keys)(int)m.WParam & Keys.KeyCode;
            bool retVal = false;

            if (m.Msg == WM_KEYDOWN)
            {
                // Handle the keypress
                label1.Text = keyCode.ToString();
            }
            return retVal;
        }
    }
}
