﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace xmlTools
{
    /// <summary>
    /// Utilities class. Contain function used along all the program and classes.
    /// </summary>
    class Util
    {
        /// <summary>
        /// Backup a file, return true if sucessful otherwise returns false
        /// </summary>
        /// <param name="file"></param>
        static public bool backupFile(string file)
        {
            try
            {
                System.IO.File.Copy(file, file + ".bak", false); //make a backup first //false is to not override already created backups
            }
            catch (Exception e)
            {
                Program.printAppError(Program.appErrors.BACKUPS_ALREADY_EXISTS, "Couldn't backup file " + file + " :\n" + e.Message);
                return false;
            }
            return true;
        }

        /// <summary>
        /// Get all elements with a determined name and optionally a parent name. Result is saved on the paremeter list "result"
        /// </summary>
        /// <param name="rootNode"></param>
        /// <param name="result"></param>
        /// <param name="posElement"></param>
        /// <param name="posParentElement"></param>
        public static void getAllSpecificElements(XmlNode rootNode, ref List<XmlNode> result, String posElement, String posParentElement = "")
        {
            foreach (XmlNode element in rootNode.ChildNodes)
            {
                if (element.Name == posElement && (posParentElement == "" || posParentElement == element.ParentNode.Name))
                {
                    result.Add(element);
                    continue;
                }
                getAllSpecificElements(element, ref result, posElement, posParentElement); //If not found in this node continue search in subnodes
            }
        }

        /// <summary>
        /// Converts a string to a xmlNode. Throws XmlException if the parsing of xml fails.
        /// </summary>
        /// <param name="xmlContent"></param>
        /// <returns></returns>
        public static XmlNode stringToXmlNode(string xmlContent)
        {
            XmlDocument doc = new XmlDocument();
            try
            {
                doc.LoadXml(xmlContent);
            }
            catch (XmlException e)
            {
                throw e;
            }
            return doc.DocumentElement;
        }

        /// <summary>
        /// Gets all xml files in the same directory of the executable
        /// </summary>
        /// <returns></returns>
        static public List<String> getAllXmlFiles()
        {
            return getXmlFilesWildcard("*.xml");
        }

        /// <summary>
        /// Converts wildcard to regex and uses it to make the match
        /// </summary>
        /// <param name="filewildcard"></param>
        /// <returns></returns>
        public static List<String> getXmlFilesWildcard(String filewildcard)
        {
            List<String> xmlFiles = new List<String>();

            String dir = Path.GetDirectoryName(filewildcard); // Get the specified directory
            if (dir == "")
            {
                dir = Util.getExePath();
            }
            String wildcard = Path.GetFileName(filewildcard); // Get files/wildcard
            String[] files = System.IO.Directory.GetFiles(dir); //Get all files in specified directory

            foreach (String file in files)
            {
                Regex wildcardRegex = new Regex(Util.WildcardToRegex(wildcard), RegexOptions.IgnoreCase); //case insensitivity
                if (wildcardRegex.IsMatch(Path.GetFileName(file)))
                {
                    xmlFiles.Add(file);
                }
            }

            return xmlFiles;
        }

        /// <summary>
        /// Converts wildcard to regex (from here: http://www.codeproject.com/Articles/11556/Converting-Wildcards-to-Regexes)
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        private static string WildcardToRegex(string pattern)
        {
            return "^" + Regex.Escape(pattern).
            Replace("\\*", ".*").
            Replace("\\?", ".") + "$";
        }

        /// <summary>
        /// Check when a string contains a wildcard or not
        /// </summary>
        /// <param name="myString"></param>
        /// <returns></returns>
        public static bool containsWildcard(String myString)
        {
            return (myString.Contains("*") || myString.Contains("?"));
        }

        public static string getExePath()
        {
            return System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
        }

        public static string getExeFileName()
        {
            return Environment.GetCommandLineArgs()[0];
        }

        public static bool IsRunningOnMono()
        {
            return Type.GetType("Mono.Runtime") != null;
        }

        public static bool ContainsIgnoreCase(string source, string sToSearch)
        {
            return source.IndexOf(sToSearch, StringComparison.OrdinalIgnoreCase) >= 0;
        }

        // Thanks DarthDevilous for the regex! http://forums.thedailywtf.com/forums/t/2478.aspx
        public static string[] stringToArgsArray(string args)
        {
            MatchCollection ms = Regex.Matches(args, "([^\" ]*(\"[^\"]*\")[^\" ]*)|[^\" ]+");
            List<string> listArgs=new List<string>();
            foreach (Match m in ms)
            {
                listArgs.Add(m.Value.Replace("\"","")); //remove quotes or it will cause an error
            }
            return listArgs.ToArray();
        }
    }
}
