/// <summary>
        /// Creates a version descriptor object from a string
        /// </summary>
        /// <param name="versionString"></param>
        public static MednafenVersionDescriptor ReturnVersionDescriptor(string versionString)
        {
            MednafenVersionDescriptor vd = new MednafenVersionDescriptor();

            vd.FullVersionString = versionString.Trim();


            // attempt splitting the string by '.'
            string[] arr = versionString.Split('.');

            int count = arr.Length;

            vd.IsValid = true;

            switch (count)
            {
            // new version format
            case 3:
                // get each version int, string
                for (int i = 0; i < count; i++)
                {
                    var result = ParseVersionInt(arr[i]);

                    if (result.Key == null)
                    {
                        vd.IsValid = false;
                    }

                    switch (i)
                    {
                    case 0:
                        vd.MajorINT = result.Key;
                        vd.MajorSTR = result.Value;
                        break;

                    case 1:
                        vd.MinorINT = result.Key;
                        vd.MinorSTR = result.Value;
                        break;

                    case 2:
                        vd.BuildINT = result.Key;
                        vd.BuildSTR = result.Value;
                        break;
                    }
                }

                vd.IsNewFormat = true;
                break;

            // old version format
            case 4:
                // get each version int, string
                for (int i = 0; i < count; i++)
                {
                    var result = ParseVersionInt(arr[i]);

                    if (result.Key == null)
                    {
                        vd.IsValid = false;
                    }

                    switch (i)
                    {
                    case 0:
                        vd.MajorINT = result.Key;
                        vd.MajorSTR = result.Value;
                        break;

                    case 1:
                        vd.MinorINT = result.Key;
                        vd.MinorSTR = result.Value;
                        break;

                    case 2:
                        vd.BuildINT = result.Key;
                        vd.BuildSTR = result.Value;
                        break;

                    case 3:
                        vd.RevisionINT = result.Key;
                        vd.RevisionSTR = result.Value;
                        break;
                    }
                }

                vd.IsNewFormat = false;
                break;

            // not valid - no more processing should take place
            default:
                vd.IsValid = false;
                return(vd);
            }

            if (vd.MajorINT > 0)
            {
                vd.IsNewConfig = true;
            }
            else
            {
                vd.IsNewConfig = false;
            }

            return(vd);
        }
        /// <summary>
        /// Parses a mednafen launch string using the compatibility matrix and removes/modifies anything
        /// that is not compatible with the user's current mednafen version
        /// </summary>
        /// <param name="launchParams"></param>
        /// <returns></returns>
        public static string GetCompatLaunchString(string launchParams)
        {
            //Versions VC = new Versions();
            string working = launchParams;

            bool isVersionValid = MednafenVersionCheck(false);

            if (isVersionValid == false)
            {
                // skip processing
                return(working);
            }

            // iterate through version changes
            foreach (MednafenChangeHistory c in GetMednafenCompatibilityMatrix())
            {
                // process changes
                foreach (var change in c.Changes)
                {
                    StringBuilder sb = new StringBuilder();

                    switch (change.ChangeMethod)
                    {
                    case ChangeType.ToRemove:                   // explicitly remove the entire command
                        string[] arr = working.Split(new string[] { " -" }, StringSplitOptions.None);
                        foreach (string s in arr)
                        {
                            if (!s.Contains(change.Item))
                            {
                                sb.Append(" -" + s);
                            }
                        }
                        working = sb.ToString();
                        break;

                    case ChangeType.ToRemoveCompletely:
                        string[] arr2 = working.Split(new string[] { " -" }, StringSplitOptions.None);
                        foreach (string s in arr2)
                        {
                            if (!s.Contains(change.Item))
                            {
                                sb.Append(" -" + s);
                            }
                        }
                        working = sb.ToString();
                        break;

                    case ChangeType.ToRename:
                        string[] arr3 = working.Split(new string[] { " -" }, StringSplitOptions.None);
                        foreach (string s in arr3)
                        {
                            if (!s.Contains(change.Item))
                            {
                                sb.Append(" -" + s);
                            }
                            else
                            {
                                sb.Append(" -" + s.Replace(change.Item, change.ChangeItem));
                            }
                        }
                        working = sb.ToString();
                        break;

                    case ChangeType.ToAdd:
                        // currently not used
                        break;
                    }
                }

                working = " -" + working.TrimStart('-').Replace("- -", "").Replace("-  -", "").TrimStart();

                string currIntOnly;
                string targetIntOnly;

                var targetDesc = MednafenVersionDescriptor.ReturnVersionDescriptor(c.Version);

                if (Instance.CurrentMedVerDesc.IsNewFormat)
                {
                    currIntOnly = Instance.CurrentMedVerDesc.MajorINT + "." +
                                  Instance.CurrentMedVerDesc.MinorINT + "." +
                                  Instance.CurrentMedVerDesc.BuildINT;

                    targetIntOnly = targetDesc.MajorINT + "." +
                                    targetDesc.MinorINT + "." +
                                    targetDesc.BuildINT;
                }
                else
                {
                    currIntOnly = Instance.CurrentMedVerDesc.MajorINT + "." +
                                  Instance.CurrentMedVerDesc.MinorINT + "." +
                                  Instance.CurrentMedVerDesc.BuildINT + "." +
                                  Instance.CurrentMedVerDesc.RevisionINT;

                    targetIntOnly = targetDesc.MajorINT + "." +
                                    targetDesc.MinorINT + "." +
                                    targetDesc.BuildINT + "." +
                                    targetDesc.RevisionINT;
                }

                if (currIntOnly == targetIntOnly)
                {
                    // we have reached the targeted version and all transformations should have been applied
                    break;
                }
            }
            return(working);
        }
        /// <summary>
        /// Entry point for the application to get mednafen version and
        /// display compatibility info if neccessary
        /// </summary>
        /// <param name="showDialog"></param>
        /// <returns></returns>
        public static bool MednafenVersionCheck(bool showDialog)
        {
            // mednafen version check
            Paths  pa            = Paths.GetPaths();
            string medFolderPath = pa.mednafenExe;
            string medPath       = medFolderPath + @"\mednafen.exe";

            if (!File.Exists(medPath))
            {
                if (showDialog)
                {
                    MessagePopper.ShowMessageDialog("Path to Mednafen is NOT valid\nPlease set this on the Settings tab",
                                                    "ERROR");
                }
                //MessageBox.Show("Path to Mednafen is NOT valid\nPlease set this on the Settings tab", "Error", MessageBoxButton.OK, MessageBoxImage.Error);

                return(false);
            }

            // detect current version
            var currDesc = Instance.CurrentMedVerDesc;

            if (currDesc == null)
            {
                if (showDialog)
                {
                    MessagePopper.ShowMessageDialog("There was a problem retreiving the Mednafen version.\nPlease check your paths",
                                                    "ERROR");
                }
                //MessageBox.Show("There was a problem retreiving the Mednafen version.\nPlease check your paths", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return(false);
            }

            if (!currDesc.IsValid)
            {
                if (showDialog)
                {
                    MessagePopper.ShowMessageDialog("There was a problem parsing the current Mednafen version.\nPlease check your paths",
                                                    "ERROR");
                }
                //MessageBox.Show("There was a problem parsing the current Mednafen version.\nPlease check your paths", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return(false);
            }

            // get the min and max support mednafen versions
            var latestDesc = Instance.LatestCompatMedVerDesc;
            var oldestDesc = MednafenVersionDescriptor.ReturnVersionDescriptor(GetMednafenCompatibilityMatrix().Last().Version);

            // check whether the current mednafen version is within the min and max supported constraints
            // just looking at the first 3 digits of the version
            string currStr = currDesc.MajorINT.ToString() + "." +
                             currDesc.MinorINT.ToString() + "." +
                             currDesc.BuildINT.ToString();

            var loookup = GetMednafenCompatibilityMatrix()
                          .Where(a => a.Version.StartsWith(currStr)).ToList();

            bool isCompat;

            if (loookup.Count() > 0)
            {
                isCompat = true;
            }
            else
            {
                isCompat = false;
            }

            if (isCompat)
            {
                // is compatible
                return(true);
            }
            else
            {
                // is not compatible
                if (showDialog)
                {
                    // version doesnt match
                    StringBuilder sb = new StringBuilder();
                    sb.Append("The version of Mednafen you are trying to launch is potentially NOT compatible with this version of MedLaunch.\n\n");
                    sb.Append("Mednafen version installed:\t");
                    sb.Append(currDesc.FullVersionString);
                    sb.Append("\nMednafen version required: \t");
                    sb.Append(oldestDesc.FullVersionString + " - " + latestDesc.FullVersionString);
                    sb.Append("\n\nPlease ensure you are targeting a MedLaunch supported version of Mednafen.\n");
                    sb.Append("\nPress LAUNCH ANYWAY to try your luck");
                    sb.Append("\nPress CANCEL to return to the Games Library");

                    var result = MessagePopper.ShowMessageDialog(sb.ToString(),
                                                                 "POSSIBLE VERSION MISMATCH", MessagePopper.DialogButtonOptions.YESNO, new MahApps.Metro.Controls.Dialogs.MetroDialogSettings
                    {
                        AnimateHide = false,
                        AnimateShow = false,
                        //ColorScheme = MahApps.Metro.Controls.Dialogs.MetroDialogColorScheme.Accented,
                        AffirmativeButtonText = "LAUNCH ANYWAY",
                        NegativeButtonText    = "CANCEL",
                    });

                    //MessageBoxResult result = MessageBox.Show(sb.ToString(), "Mednafen Version Error", MessageBoxButton.OKCancel, MessageBoxImage.Error);
                    if (result == MessagePopper.ReturnResult.Affirmative)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
            }
        }
        /// <summary>
        /// Attempts to parse data from either stdout or console
        /// </summary>
        public void ParseData()
        {
            // check whether this is the first parse or not (so it has to be forced)
            if (IsInit)
            {
                IsDirty = true;
                IsInit  = false;
            }


            Paths paths = Paths.GetPaths();

            if (paths != null)
            {
                LogPath     = paths.mednafenExe + @"\stdout.txt";
                MednafenEXE = paths.mednafenExe + @"\mednafen.exe";
            }

            if (!IsDirty)
            {
                return;
            }

            // With mednafen >= 1.21.0 we can now call mednafen from an existing console and get
            // the required output from the console itself - try this method first
            // if no data is returned check stdout.txt
            if (File.Exists(MednafenEXE))
            {
                // first try new method
                string args = "\"" + MednafenEXE + "\" EmptyTriggerConsole";

                /*
                 *
                 * var conProcess = new Process
                 * {
                 *  StartInfo = new ProcessStartInfo
                 *  {
                 *      FileName = "cmd.exe",
                 *      //Arguments = args,
                 *      UseShellExecute = false,
                 *      RedirectStandardOutput = true,
                 *      RedirectStandardInput = true,
                 *      CreateNoWindow = true,
                 *      WindowStyle = ProcessWindowStyle.Hidden
                 * }
                 * };
                 *
                 * // set the environment variable to hide popups
                 * conProcess.StartInfo.EnvironmentVariables["MEDNAFEN_NOPOPUPS"] = "1";
                 *
                 * conProcess.Start();
                 * int procId = conProcess.Id;
                 *
                 * conProcess.StandardInput.WriteLine(args);
                 * conProcess.StandardInput.Flush();
                 * conProcess.StandardInput.Close();
                 *
                 * Output = string.Empty;
                 *
                 * while (!conProcess.StandardOutput.EndOfStream)
                 * {
                 *  string line = conProcess.StandardOutput.ReadLine();
                 *  Output += line;
                 *  Output += "\n";
                 * }
                 *
                 * if (!Output.Contains("Starting Mednafen"))
                 * {
                 *
                 */
                // no output detected - try old method
                Output = string.Empty;

                //Thread.Sleep(500);

                var winProcess = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName        = MednafenEXE,
                        Arguments       = "EmptyTriggerWindow",
                        WindowStyle     = ProcessWindowStyle.Hidden,
                        CreateNoWindow  = true,
                        UseShellExecute = false
                    }
                };

                // set the environment variable to hide popups
                winProcess.StartInfo.EnvironmentVariables["MEDNAFEN_NOPOPUPS"] = "1";

                winProcess.Start();
                winProcess.WaitForExit();

                // attempt to read from stdout.txt
                // check whether stdout.txt doesnt exist or not
                if (!File.Exists(LogPath))
                {
                    Thread.Sleep(10);
                    ParseData();
                    Thread.Sleep(10);

                    if (!File.Exists(LogPath))
                    {
                        Output = string.Empty;
                    }
                    else
                    {
                        var ar = FileAndFolder.StreamAllLines(LogPath);
                        foreach (var a in ar)
                        {
                            Output += a + "\n";
                        }
                    }
                }
                else
                {
                    var ar = FileAndFolder.StreamAllLines(LogPath);
                    foreach (var a in ar)
                    {
                        Output += a + "\n";
                    }
                }

                /*
                 * }
                 */

                // attempt to parse the output
                List <string> list = Output.Replace("\r", "\n").Split('\n').ToList();

                if (list.Count() < 1 || list == null)
                {
                    // no data
                    return;
                }

                // get version info
                string versionLine = (from a in list
                                      where a.Contains(" Mednafen ")
                                      select a).FirstOrDefault();

                if (versionLine != null && versionLine.Trim() != "")
                {
                    // split line
                    string[] spl = versionLine.Split(new string[] { "Mednafen " }, StringSplitOptions.None);

                    // get the last item in the array (the version number)
                    VersionString = spl.Last().Trim();

                    // process version number
                    MedVersionDesc = MednafenVersionDescriptor.ReturnVersionDescriptor(VersionString);
                }

                IsDirty = false;

                // get joystick IDs
                Controllers.Clear();

                if (VersionChecker.Instance.IsNewConfig)
                {
                    // new version
                    var lines = list.Where(a => a.Contains("ID: ")).ToList();

                    foreach (var l in lines)
                    {
                        ControllerInfo ci = new ControllerInfo();

                        if (l.ToLower().Contains("xinput") ||
                            l.ToLower().Contains("XBOX 360") ||
                            l.Contains("00000000000000000001"))
                        {
                            // mednafen has probably detected this as an xinput controller
                            ci.Type = ControllerType.XInput;
                        }
                        else
                        {
                            // mednafen has probably detected this as a directinput controller
                            ci.Type = ControllerType.DirectInput;
                        }

                        // split the string up
                        string[] arr  = l.TrimStart().Replace("ID: ", "").Split(new string[] { " - " }, StringSplitOptions.None);
                        string   ID   = arr[0]; //.TrimStart('0').TrimStart('x');
                        string   Name = arr[1].Trim();

                        ci.ID   = ID;
                        ci.Name = Name;

                        Controllers.Add(ci);
                    }
                }
                else
                {
                    // old version
                    var lines = list.Where(a => a.TrimStart().StartsWith("Joystick ")).ToList();

                    foreach (var l in lines)
                    {
                        ControllerInfo ci = new ControllerInfo();

                        if (l.ToLower().Contains("xinput") ||
                            l.ToLower().Contains("XBOX 360") ||
                            l.Contains("000000000001"))
                        {
                            // mednafen has probably detected this as an xinput controller
                            ci.Type = ControllerType.XInput;
                        }
                        else
                        {
                            // mednafen has probably detected this as a directinput controller
                            ci.Type = ControllerType.DirectInput;
                        }

                        string trimmed = l.Trim();

                        // split the string up
                        string[] arr = trimmed.Split(new string[] { " - " }, StringSplitOptions.None);
                        ci.Name = arr[1];
                        ci.ID   = arr[2].Replace("Unique ID: ", "");

                        Controllers.Add(ci);
                    }
                }



                IsDirty = false;
            }
        }