using Microsoft.Win32;
using MindFusion.Diagramming.Wpf;
using MindFusion.Diagramming.Wpf.Layout;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Photoalbum
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

            //set link styling
            diagram.LinkHeadShapeSize = 12;
            diagram.LinkHeadShape = ArrowHeads.Triangle;

            //create a new theme
            Theme theme = new Theme();

            //create a style for the links
            Style linkStyle = new Style();
            linkStyle.Setters.Add(new Setter(DiagramLink.BrushProperty, new SolidColorBrush(Color.FromRgb(245, 245, 240))));
            linkStyle.Setters.Add(new Setter(DiagramLink.StrokeProperty, new SolidColorBrush(Color.FromRgb(191, 191, 191))));
            linkStyle.Setters.Add(new Setter(DiagramLink.HeadStrokeProperty, new SolidColorBrush(Color.FromRgb(191, 191, 191))));
            //register the style with the theme
            theme.RegisterStyle(typeof(DiagramLink), linkStyle);
            //create a style for the nodes
            Style nodeStyle = new Style();
            nodeStyle.Setters.Add(new Setter(ShapeNode.StrokeProperty, new SolidColorBrush(Color.FromRgb(191, 191, 191))));
            nodeStyle.Setters.Add(new Setter(ShapeNode.FontFamilyProperty, new FontFamily("Lato")));
            //register the style with the theme
            theme.RegisterStyle(typeof(ShapeNode), nodeStyle);
            //assign the theme
            diagram.Theme = theme;
        }

        //handle the Window_Loaded event
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

            textBlock.Text = "The photoalbum example represents a tree-layout gallery."+
                " By right-clicking on a folder the user can add a subfolder or a new image."+
                " The user can also move images and folders by drag-and-droping them onto their new parent"+
                " or deleting diagram items by selecting one or several and pressing the Del button.";

            // Create the hierarchy

            string[] labels = new string[] {"Images", "Events", "Family", "Tourism",
                "Autoexibition 2014 Detroit", "Depeche Mode Concert 2016", "Third March",
                "Lia`s birthday", "New year 2017", "Sam`s graduation",
                "Brazil and Argentina", "Italy 2013", "Summer 2017"};
             
            //create the initial nodes for the album
            for(int i = 0; i < labels.Length; i++)
            {
                var node = CreateFolder(labels[i]);
                diagram.Nodes.Add(node);
            }

            int length = 0;
            // reads the initial subfolders for the album 
             string[] subfolders = System.IO.Directory.GetDirectories(path);
            string[] folders = new string[9];

            //goes one level deeper into the hierarchy
            for (int i = 0; i < subfolders.Length; i++)
            {
                string[] subsubfolders = System.IO.Directory.GetDirectories(subfolders[i]);
                for(int j = 0; j < subsubfolders.Length; j++)
                {
                    folders[length] = subsubfolders[j];
                    length++;
                }
            }

            //loads the images for each folder
            for(int i = 0; i < folders.Length; i++)
            {
                string[] filenames = System.IO.Directory.GetFiles(folders[i]);
                LoadImages(filenames, diagram.Nodes.GetAt(i + 4) as ShapeNode);
            }

            //create links between the root and all subfolders
            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(0) as ShapeNode, diagram.Nodes.GetAt(1) as ShapeNode);
            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(0) as ShapeNode, diagram.Nodes.GetAt(2) as ShapeNode);
            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(0) as ShapeNode, diagram.Nodes.GetAt(3) as ShapeNode);

            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(1) as ShapeNode, diagram.Nodes.GetAt(4) as ShapeNode);
            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(1) as ShapeNode, diagram.Nodes.GetAt(5) as ShapeNode);
            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(1) as ShapeNode, diagram.Nodes.GetAt(6) as ShapeNode);

            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(2) as ShapeNode, diagram.Nodes.GetAt(7) as ShapeNode);
            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(2) as ShapeNode, diagram.Nodes.GetAt(8) as ShapeNode);
            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(2) as ShapeNode, diagram.Nodes.GetAt(9) as ShapeNode);

            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(3) as ShapeNode, diagram.Nodes.GetAt(10) as ShapeNode);
            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(3) as ShapeNode, diagram.Nodes.GetAt(11) as ShapeNode);
            diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(3) as ShapeNode, diagram.Nodes.GetAt(12) as ShapeNode);

            Rearrange();
        }

        //creates a new folder with the specified text.
        private ShapeNode CreateFolder(string text)
        {
            var node = new ShapeNode();
            node.Text = text;
            node.Tag = "Folder";
            node.Transparent = true;
            node.TextAlignment = TextAlignment.Center;
            node.TextVerticalAlignment = AlignmentY.Center;
            node.Expandable = true;
            BitmapImage image = this.FindResource("Folder") as BitmapImage;
            node.Image = image;
            node.ResizeToFitImage();
            return node;
        }

        /// <summary>
        /// Creates a new Node that holds an image
        /// </summary>
        /// <param name="path">The path to the image.</param>
        /// <returns>The node that represets the image.</returns>
        private ShapeNode CreateImage(string path)
        {
            var node = new ShapeNode();
            //customize the node appearance
            node.Shape = Shapes.RoundRect;
            node.Brush = new SolidColorBrush(Color.FromRgb(245, 245, 240));
            node.Tag = "";
            //assign the image
            Uri imageUri = new Uri(path, UriKind.Relative);
            BitmapImage image = new BitmapImage(imageUri);
            node.Image = image;
            return node;
        }

        /// <summary>
        /// Loads the specified images as children to the specified node.
        /// </summary>
        /// <param name="filenames">A list with the files that contain the images.</param>
        /// <param name="parent">The parent node.</param>
        private void LoadImages(string[] filenames, DiagramNode parent)
        {
            for (int i = 0; i < filenames.Length; i++)
            {
                var node = CreateImage(filenames[i]);
                diagram.Nodes.Add(node);
                diagram.Factory.CreateDiagramLink(parent, node);
            }
        }

        /// <summary>
        /// Rearranges the diagram.
        /// </summary>
        private void Rearrange()
        {
            if (layout == null)
            {
                layout = new TreeLayout(diagram.Nodes.GetAt(0),
                    TreeLayoutType.Centered,
                    false,
                    TreeLayoutLinkType.Cascading3,
                    TreeLayoutDirections.TopToBottom,
                    40, 20, true, new Size(15, 15));
            }

            layout.Arrange(diagram);
        }

        /// <summary>
        /// Creates a new folder.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">RoutedEventArgs with data for the event.</param>
        private void AddFolderMenuItem_Click(object sender, RoutedEventArgs e)
        {
            NewFolderDlg dialog = new NewFolderDlg();
            if (dialog.ShowDialog() == true)
            {
                //create a new node with the specified name.
                var node = CreateFolder(dialog.FolderName);
                //add the node to the nodes collection
                diagram.Nodes.Add(node);
                //cretae a link between the selected node and the new node.
                if (SelectedNode != null)
                    diagram.Factory.CreateDiagramLink(SelectedNode, node);
                //rearrange the tree.
                Rearrange();
            }
        }

        /// <summary>
        /// Adds an image.
        /// </summary>
        /// <param name="sender">The node that raised the event.</param>
        /// <param name="e">RoutedEventArgs object with data for the event.</param>
        private void AddImageMenuItem_Click(object sender, RoutedEventArgs e)
        {
            //choose image files.
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "Image files| *.png;*.jpg;";
            if (dialog.ShowDialog() == true)
            {
                //Creates an image node
                var node = CreateImage(dialog.FileName);
                //add the node to the other nodes
                diagram.Nodes.Add(node);
                //link the selected node and the new node
                if (SelectedNode != null)
                    diagram.Factory.CreateDiagramLink(SelectedNode, node);
                Rearrange();
            }
        }

       //handles the NodeClicked event
        private void diagram_NodeClicked(object sender, NodeEventArgs e)
        {
            //gets the node that was clicked
            SelectedNode = e.Node as ShapeNode;
            if (e.MouseButton == MindFusion.Diagramming.Wpf.MouseButton.Right && SelectedNode.Tag.ToString().Length > 0)
            {
                //renders the context menu
                ContextMenu cm = this.FindResource("ContextMenu") as ContextMenu;
                cm.Placement = System.Windows.Controls.Primitives.PlacementMode.Mouse;
                cm.IsOpen = true;
            }
        }

        //handles the NodeModified event
        private void diagram_NodeModified(object sender, NodeEventArgs e)
        {
            //gets the nodes at the specified mouse position
            if (diagram.GetNodesAt(e.MousePosition).Count != 1)
            {
                ShapeNode child = e.Node as ShapeNode;
                ShapeNode parent = null;
                bool parentIsFolder = false;
                foreach (ShapeNode node in diagram.GetNodesAt(e.MousePosition))
                {
                    //check if the node is a folder
                    if (node.Tag.ToString().Length > 0 && node != child)
                    {
                        parent = node;
                        parentIsFolder = true;
                    }
                }
                //removes the current link between the node and its parent
                if (parentIsFolder)
                {
                    if (child.IncomingLinks.GetAt(0) as DiagramLink != null)
                        diagram.Links.Remove(child.IncomingLinks.GetAt(0) as DiagramLink);
                }
                //creates a new link
                diagram.Factory.CreateDiagramLink(parent, child);
            }
            Rearrange();
        }

        private TreeLayout layout = null;
        private ShapeNode SelectedNode = null;
        private const string path = @".\Images";
    }
}
