using System.Text.RegularExpressions;
using System.Windows;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace APE.model
{
    public class FileStructure
    {
        public RootNode root;
		public AbstractNode leaf;
		public List<AbstractNode> nodesOnPath = new List<AbstractNode>();

		//public ObservableCollection<AbstractNode> PublishedNodes { get;	private set; }

        public FileStructure(string loadThis)
        {
            root = new RootNode();
            root.accept(new FSLoadVisitor());
            AbstractNode currentNode = root;

            if (!isCorrectPath(loadThis)) {				
				loadThis = ""; 
			}

            string currentDirName;
			nodesOnPath.Add(currentNode);
            while (loadThis.Length != 0) {
                currentDirName = loadThis.Substring(0, loadThis.IndexOf(@"\"));
                loadThis = loadThis.Substring(loadThis.IndexOf(@"\") + 1);
                foreach (AbstractNode fN in currentNode.children) { 
					fN.accept(new FSLoadVisitor()); 
                    if (currentDirName == fN.Name) {
						/// This works because in file system,
						/// there is only one directory with given name.
						/// In theory I could skip loading of other nodes,
						/// but why add one more condition into cycle?
                        currentNode = fN;
						currentNode.isOnCurrentPath = true;
						currentNode.loadChildren();
                    }
				}
				nodesOnPath.Add(currentNode);
            }
			leaf = currentNode;
			//createObservableCollection(leaf);
        }

		public void goDeeper(AbstractNode node) {
			nodesOnPath.Add(node);
			leaf = node;
			leaf.accept(new FSLoadVisitor());
			//createObservableCollection(leaf);
		}


		/// <summary>
		/// In the future, it will be needed to refactor this project into MVVM pattern.
		/// This method is left here as a remainder of that effort.
		/// </summary>
		//private void createObservableCollection(AbstractNode source) {
		//    if (PublishedNodes.Count != 0) {
		//        PublishedNodes.Clear();
		//    }
		//    foreach (AbstractNode n in source.children) {
		//        PublishedNodes.Add(n);
		//    }
		//}

        static public bool isCorrectPath(string dir)
        {
            string FSPathPattern = @"
	                                   ^$ |
                                       ^
											[A-Z]:\\
                                            ([\w]+\\)*
                                       $
                                   ";
            if (!Regex.IsMatch(dir, FSPathPattern, RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace)) {
				System.Diagnostics.Debug.WriteLine("Startup string is not valid! Using Root as the initial folder.");
                return false;
            } else {
                return true;
            }
        }

        static public bool hasCorrectChars(string name)
        {
            foreach (char c in name)
            {
                switch (c)
                {
                    case '<':
                    case '>':
                    case ':':
                    case '"':
                    case '/':
                    case '\\':
                    case '|':
                    case '?':
                    case '*':
                        System.Diagnostics.Debug.WriteLine("Character '" + c + "' is not allowed in the file name.");
                        return false;
                    default:
                        break;
                }
            }
            return true;
        }

		public void goBack() {
			if (nodesOnPath.Count < 2) {
				return;
			}
			nodesOnPath.Remove(leaf);
			leaf = nodesOnPath[nodesOnPath.Count - 1];
			leaf.accept(new FSLoadVisitor());
		}

		public void refresh() { 
			for (int i = 0; i < nodesOnPath.Count; i++) {
				try {
					nodesOnPath[i].accept(new FSLoadVisitor());
					nodesOnPath[i].loadChildren();
				} catch (System.UnauthorizedAccessException exc) {
					System.Diagnostics.Debug.WriteLine(exc.Message);
				} catch (System.Security.SecurityException exc) {
					System.Diagnostics.Debug.WriteLine(exc.Message);
				}
				if (i == nodesOnPath.Count - 1) {
					break;
				}
				bool childExists = false;
				foreach (AbstractNode child in nodesOnPath[i].children) {
					if (child.Name == nodesOnPath[i + 1].Name) {
						childExists = true;
					}
				}
				if (!childExists) {
					nodesOnPath.RemoveRange(i + 1, -1);
					leaf = nodesOnPath[i];
					break;
				}
			}
		}
	}
}
