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

namespace DataOrganizer
{
    public partial class ProfileManager : Form
    {
        private string MachineNameLabelText { get; } = "The Machine Name property determines what profile will be loaded automatically.\r\nCurrently: '{0}'.";
        private bool IsUpdating { get; set; }
        private ContextMenu FolderGroupListContextMenu { get; set; } = new ContextMenu();
        private List<DB.Namingconvention> NamingConventions { get; }
        private Dictionary<string, DB.Profile> Profiles { get; } = new Dictionary<string, DB.Profile>();
        private Dictionary<string, DB.FolderGroup> FolderGroups { get; } = new Dictionary<string, DB.FolderGroup>();

        public ProfileManager()
        {
            InitializeComponent();

            var db = new DB();
            var deleteMenuItem = new MenuItem("Delete");
            FolderGroupListContextMenu.MenuItems.Add(deleteMenuItem);
            NamingConventions = db.GetNamingConventions();
            NamingConventionComboBox.Items.Add("None");
            NamingConventionComboBox.SelectedIndex = 0;

            foreach(var convention in NamingConventions)
            {
                NamingConventionComboBox.Items.Add(convention.Name);
            }

            ProfilesComboBox.SelectedIndexChanged += ProfilesComboBox_SelectedIndexChanged;
            ProfileNameTextBox.TextChanged += ToggleAddOrUpdateButton;
            NewContentLocationTextBox.TextChanged += ToggleAddOrUpdateButton;
            MachineNameTextBox.TextChanged += MachineNameTextBox_TextChanged;
            FolderGroupPathTextBox.TextChanged += ToggleGroupInsertButton;
            FolderGroupListView.MouseClick += FolderGroupListView_MouseClick;
            deleteMenuItem.Click += DeleteMenuItem_Click;

            PopulateProfiles();
            SetupForNewProfile();
        }

        private void FolderGroupListView_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                FolderGroupListContextMenu.Show(FolderGroupListView, e.Location);
            }
            else if (e.Button == MouseButtons.Left)
            {
                GetSelectedFolderGroup(out DB.FolderGroup folderGroup);
                FolderGroupPathTextBox.Text = folderGroup.Path;
                FolderNameTextBox.Text = folderGroup.Name;
                var index = NamingConventions.FindIndex(x => x.Id == folderGroup.PatternId);

                if (index != -1)
                    NamingConventionComboBox.SelectedIndex = index + 1;
                else
                    NamingConventionComboBox.SelectedIndex = 0;

                InsertGroupName.Text = "Update Folder Group";
            }
        }

        private void DeleteMenuItem_Click(object sender, EventArgs e)
        {
            if(IsUpdating)
            {
                var result = MessageBox.Show("Are you sure you want to delete this group? Doing so will delete all records associated with it?", "Confirm Group Deletion", MessageBoxButtons.YesNo);

                if(result == DialogResult.Yes)
                {
                    var db = new DB();

                    GetSelectedFolderGroup(out DB.FolderGroup folderGroup);

                    db.DeleteFolderGroup(folderGroup);

                    RemoveFolderGroup(folderGroup.Id);
                }
            }
            else
            {
                FolderGroupListView.Items.Remove(FolderGroupListView.SelectedItems[0]);
            }
        }

        private void MachineNameTextBox_TextChanged(object sender, EventArgs e)
        {
            if (MachineNameTextBox.Text.Length > 0)
                MachineNameLabel.Text = string.Format(MachineNameLabelText, MachineNameTextBox.Text);
            else
                MachineNameLabel.Text = string.Format(MachineNameLabelText, Environment.MachineName);
        }

        private void ToggleAddOrUpdateButton(object sender, EventArgs e)
        {
            if (ProfileNameTextBox.Text != string.Empty && NewContentLocationTextBox.Text != string.Empty)
                AddOrUpdateProfileButton.Enabled = true;
            else 
                AddOrUpdateProfileButton.Enabled = false;
        }

        private void ToggleGroupInsertButton(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(FolderGroupPathTextBox.Text))
                InsertGroupName.Enabled = true;
            else
                InsertGroupName.Enabled = false;
        }

        private void AddOrUpdateProfileButton_Click(object sender, EventArgs e)
        {
            var machineName = Environment.MachineName;
            var db = new DB();

            if(!string.IsNullOrWhiteSpace(MachineNameTextBox.Text))
            {
                machineName = MachineNameTextBox.Text;
            }

            if (!IsUpdating)
            {
                var folders = new List<DB.FolderGroup>();
                //TODO: crash
                foreach(ListViewItem node in FolderGroupListView.Items)
                {
                    folders.Add(FolderGroups[node.Text]);
                }

                var newProfile = new DB.Profile { Name = ProfileNameTextBox.Text, DefaultNewContentFolder = NewContentLocationTextBox.Text, MachineName = machineName, FolderGroups = folders };

                db.InsertNewProfile(newProfile);

                Profiles.Add(newProfile.Name, newProfile);
                ProfilesComboBox.Items.Add(newProfile.Name);
            }
            else
            {
                GetCurrentProfile(out DB.Profile profile);
                profile.Name = ProfileNameTextBox.Text;
                profile.DefaultNewContentFolder = NewContentLocationTextBox.Text;
                profile.MachineName = MachineNameTextBox.Text;

                Profiles[profile.Name] = profile;

                db.UpdateProfile(profile);
            }

            SetupForNewProfile();
        }

        private void ProfilesComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (ProfilesComboBox.SelectedIndex == 0)
                SetupForNewProfile();
            else
                SetUpFormForUpdatingProfile();
        }

        private void InsertGroupName_Click(object sender, EventArgs e)
        {
            FolderGroupPathTextBox.Text = FolderGroupPathTextBox.Text.TrimEnd(new char[] { '\\' });

            var dir = new DirectoryInfo(FolderGroupPathTextBox.Text);
            var groupName = dir.Name;

            if (!FolderGroups.ContainsKey(groupName))
            {
                GetCurrentNamingConvention(out DB.Namingconvention convention);
                GetCurrentProfile(out DB.Profile profile);
                var newFolder = new DB.FolderGroup { Name = groupName, Path = FolderGroupPathTextBox.Text, PatternId = convention.Id};

                FolderGroupListView.Items.Add(groupName);

                if (IsUpdating)
                {
                    var db = new DB();

                    var newId = db.InsertNewFolderGroup(profile, groupName, FolderGroupPathTextBox.Text, convention.Id);
                    newFolder.Id = newId;

                    profile.FolderGroups.Add(newFolder);

                    Profiles[profile.Name] = profile;
                }

                FolderGroups.Add(newFolder.Name, newFolder);

                FolderNameTextBox.Text = string.Empty;
                FolderGroupPathTextBox.Text = string.Empty;
                InsertGroupName.Enabled = false;
            }
            else
            {
                var folderGroup = FolderGroups[groupName];//(DB.FolderGroup) FolderGroupListView.Items.Find(groupName, true)[0].Tag;
                folderGroup.Path = FolderGroupPathTextBox.Text;
                folderGroup.Name = groupName;
                GetCurrentNamingConvention(out DB.Namingconvention convention);
                folderGroup.PatternId = convention.Id;
                InsertGroupName.Text = "Insert Folder Group";

                if (IsUpdating)
                {
                    var db = new DB();
                    db.UpdateFolderGroup(folderGroup);
                }

                FolderGroups[groupName] = folderGroup;

                NamingConventionComboBox.SelectedIndex = 0;
                FolderNameTextBox.Text = string.Empty;
                FolderGroupPathTextBox.Text = string.Empty;
                InsertGroupName.Enabled = false;
            }

            FolderGroupPathButton.Focus();
        }

        private bool GetCurrentProfile(out DB.Profile profile)
        {
            profile = new DB.Profile();

            if (!IsUpdating) return false;

            profile = Profiles[ProfilesComboBox.Text];

            return true;
        }

        private bool GetCurrentNamingConvention(out DB.Namingconvention namingconvention)
        {
            namingconvention = new DB.Namingconvention();

            if (NamingConventions.Count == 0 || NamingConventionComboBox.SelectedIndex == 0) return false;

            namingconvention = NamingConventions[NamingConventionComboBox.SelectedIndex - 1];

            return true;
        }

        private bool GetSelectedFolderGroup(out DB.FolderGroup folderGroup)
        {
            folderGroup = new DB.FolderGroup();

            if(FolderGroupListView.SelectedItems.Count == 1)
            {
                folderGroup = FolderGroups[FolderGroupListView.SelectedItems[0].Text];
                return true;
            }

            return false;
        }

        private void DeleteProfileButton_Click(object sender, EventArgs e)
        {
            var result = MessageBox.Show("Are you sure? This will delete all file records (not files on disk), groups and any customization data set in this profile.", "Wipe Profile", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);

            if(result == DialogResult.Yes)
            {
                var db = new DB();
                GetCurrentProfile(out DB.Profile profile);

                db.DeleteProfile(profile);

                PopulateProfiles();
                SetupForNewProfile();
            }
        }

        private void FolderGroupPathButton_Click(object sender, EventArgs e)
        {
            var dialog = new FolderBrowserDialog() { Description = "Select a root folder that holds like content." };

            if(dialog.ShowDialog() == DialogResult.OK)
            {
                FolderGroupPathTextBox.Text = dialog.SelectedPath;
                InsertGroupName.Text = "Insert Folder Group";
            }
        }

        private void RemoveFolderGroup(int folderId)
        {
            GetCurrentProfile(out DB.Profile profile);

            profile.FolderGroups.RemoveAll(x => x.Id == folderId);

            ClearFolderGroupControls();

            foreach(var folder in profile.FolderGroups)
            {
                var item = new ListViewItem(folder.Name);
                item.Tag = folder;
                FolderGroupListView.Items.Add(item);
            }
        }

        private void ClearForm()
        {
            ClearProfileDataControls();
            ClearFolderGroupControls();
        }

        private void ClearFolderGroupControls()
        {
            FolderGroupListView.Items.Clear();
            NamingConventionComboBox.SelectedIndex = 0;
            FolderNameTextBox.Text = string.Empty;
            FolderGroupPathTextBox.Text = string.Empty;
            InsertGroupName.Enabled = false;
        }

        private void ClearProfileDataControls()
        {
            ProfileNameTextBox.Text = string.Empty;
            NewContentLocationTextBox.Text = string.Empty;
            MachineNameTextBox.Text = string.Empty;
            DeleteProfileButton.Enabled = false;
            AddOrUpdateProfileButton.Enabled = false;
            AddOrUpdateProfileButton.Text = "Add";
        }

        private void PopulateProfiles()
        {
            ProfilesComboBox.SelectedIndexChanged -= ProfilesComboBox_SelectedIndexChanged;

            var db = new DB();
            Profiles.Clear();

            var profiles = db.GetProfiles();

            foreach(var profile in profiles)
            {
                Profiles.Add(profile.Name, profile);
            }

            ProfilesComboBox.Items.Clear();
            ProfilesComboBox.Items.Add("Add New Profile");
            ProfilesComboBox.SelectedIndex = 0;

            if (Profiles.Count == 0)
                ProfilesComboBox.Enabled = false;
            else
            {
                ProfilesComboBox.Enabled = true;

                foreach (var profile in Profiles)
                {
                    ProfilesComboBox.Items.Add(profile.Value.Name);
                }
            }

            ProfilesComboBox.SelectedIndexChanged += ProfilesComboBox_SelectedIndexChanged;
        }

        private void RefreshProfileComboBox()
        {
            ProfilesComboBox.SelectedIndexChanged -= ProfilesComboBox_SelectedIndexChanged;

            ProfilesComboBox.Items.Clear();
            ProfilesComboBox.Items.Add("Add New Profile");
            ProfilesComboBox.SelectedIndex = 0;

            if (Profiles.Count == 0)
                ProfilesComboBox.Enabled = false;
            else
            {
                ProfilesComboBox.Enabled = true;

                foreach (var profile in Profiles)
                {
                    ProfilesComboBox.Items.Add(profile.Value.Name);
                }
            }

            ProfilesComboBox.SelectedIndexChanged += ProfilesComboBox_SelectedIndexChanged;
        }

        private void SetupForNewProfile()
        {
            ClearForm();
            RefreshProfileComboBox();
            IsUpdating = false;
            FolderGroups.Clear();

            MachineNameLabel.Text = string.Format(MachineNameLabelText, Environment.MachineName);
            AddOrUpdateProfileButton.Text = "Add";
            ProfileNameTextBox.Focus();
        }

        private void SetUpFormForUpdatingProfile()
        {
            ClearForm();
            IsUpdating = true;

            GetCurrentProfile(out DB.Profile profile);

            ProfileNameTextBox.Text = profile.Name;
            NewContentLocationTextBox.Text = profile.DefaultNewContentFolder;
            MachineNameTextBox.Text = profile.MachineName;
            MachineNameLabel.Text = string.Format(MachineNameLabelText, profile.MachineName);
            FolderGroups.Clear();

            if (profile.FolderGroups != null)
            {
                foreach (var group in profile.FolderGroups)
                {
                    FolderGroupListView.Items.Add(group.Name);
                    FolderGroups.Add(group.Name, group);
                }
            }

            AddOrUpdateProfileButton.Text = "Update";
            AddOrUpdateProfileButton.Enabled = true;
            DeleteProfileButton.Enabled = true;
        }

        private void SelectNewContentLocationButton_Click(object sender, EventArgs e)
        {
            var dialog = new FolderBrowserDialog() { Description = "Select the default location to look for new content." };

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                NewContentLocationTextBox.Text = dialog.SelectedPath;
            }
        }
    }
}
