static void Main(string[] args)
        {
            var optionValues = new OptionValues();
            var options      = new OptionSet
            {
                { "h|help", "Show this message and exit.", s => optionValues.ShowHelp = s != null },
                {
                    "e={:}|encoder={:}",
                    new StringBuilder().AppendLine("The {0:ENCODER TYPE} and {1:QUALITY} value to use. ")
                    .AppendLine()
                    .AppendLine("Valid {0:ENCODER TYPE} values are: ")
                    .AppendLine()
                    .AppendLine("fhgaacenc")
                    .AppendLine("lame")
                    .AppendLine("nero")
                    .AppendLine("oggvorbis")
                    .AppendLine("qaac")
                    .AppendLine("qaac64")
                    .AppendLine()
                    .Append("Numeric {1:QUALITY} values are specific to each encoder ")
                    .AppendLine("(fhgaacenc uses a value between 1 and 6, qaac uses 0 to 127, etc.) ")
                    .AppendLine()
                    .AppendLine("VBR mode is always used.")
                    .AppendLine()
                    .Append("These encoders are not distributed with this program. ")
                    .Append("They must be installed separately and copied to the executable directory ")
                    .Append("or made accessible via the System PATH environment variable. ")
                    .ToString(),
                    (string encStr, decimal encQual) =>
                    {
                        optionValues.EncoderString  = encStr;
                        optionValues.EncoderQuality = encQual;
                    }
                },
                {
                    "i=|input=",
                    new StringBuilder().AppendLine("The {PATH} to the cue sheet file.")
                    .AppendLine()
                    .Append("FLAC, WavPack and Monkey's Audio* files can be split. ")
                    .Append("Decoders for these files are not distributed with this program. ")
                    .Append("They must be installed separately and copied to the executable directory ")
                    .Append("or made accessible via the System PATH environment variable. ")
                    .AppendLine()
                    .AppendLine()
                    .Append("*Ensure the FLAC decoder is installed if splitting Monkey's Audio files. ")
                    .Append("MAC.exe does not provide any splitting functionality so a transcode to FLAC is required.")
                    .ToString(),
                    s => optionValues.CueFilePath = s
                },
                { "o=|output=", "The output {PATH}.", s => optionValues.OutputPath = s },
                { "c=|cover=", "The {PATH} to a front cover image.", s => optionValues.CoverPath = s }
            };

            List <string> extra;

            try
            {
                extra = options.Parse(args);

                if (optionValues.ShowHelp)
                {
                    options.WriteOptionDescriptions(Console.Out);
                    return;
                }

                optionValues.Validate();

                var cueSheetParser = new CueSheetParser(optionValues.CueFilePath);

                CueSheet cueSheet = cueSheetParser.Parse().ToTitleCase();

                var splitterFactory = new SplitterFactory(cueSheet, optionValues.CueFilePath);
                var encoderFactory  = new EncoderFactory(optionValues.EncoderQuality);
                var taggerFactory   = new TaggerFactory(cueSheet, optionValues.CoverPath);
                var stopwatch       = new Stopwatch();

                IEncoder encoder = encoderFactory.Build(optionValues.EncoderType);
                ITagger  tagger  = taggerFactory.Build(optionValues.EncoderType);
                using (ISplitter splitter = splitterFactory.Build())
                {
                    Console.WriteLine("Starting...");
                    Console.WriteLine("Splitting {0} cue sheet into WAV files...", BuildCuesheetTypeStr(cueSheet));

                    stopwatch.Start();

                    splitter.Split();

                    DirectoryInfo encodedOutputDirInfo = Directory.CreateDirectory(Path.Combine(optionValues.OutputPath, encoder.FileType));

                    int trackCountWidth = cueSheet.IsStandard
                        ? cueSheet.Files[0].Tracks.Count.ToString().Length
                        : cueSheet.Files.Count.ToString().Length;

                    Parallel.ForEach(
                        splitter.Results,
                        trackWavPair =>
                    {
                        Track track        = trackWavPair.Track;
                        string wavFilePath = trackWavPair.FilePath;
                        string title       = track.Title.Trim();

                        Console.WriteLine(
                            "Encoding '{0}' to {1} (Thread {2})...",
                            title,
                            encoder.FileType,
                            Thread.CurrentThread.ManagedThreadId);

                        string tempEncodedFilePath = encoder.Encode(wavFilePath, track, tagger);

                        string encodedOutputPath = BuildEncodedFileOutputPath(
                            encodedOutputDirInfo.FullName,
                            title,
                            track.TrackNum,
                            trackCountWidth,
                            encoder.FileExtension);

                        IOUtils.FileMove(tempEncodedFilePath, encodedOutputPath);
                    });
                }

                Console.WriteLine("Copying original files to output directory...");

                CopyOriginalsToOutputPath(optionValues.OutputPath, optionValues.CueFilePath, cueSheet, optionValues.CoverPath);

                stopwatch.Stop();

                Console.WriteLine("Done. Time elapsed: {0}", stopwatch.Elapsed);
            }
            catch (OptionException e)
            {
                Console.WriteLine("{0} {1}", e.OptionName, e.Message);
                Console.WriteLine("Try '--help' for more information.");
            }

            if (Debugger.IsAttached)
            {
                Console.WriteLine("Click any key to exit.");
                Console.ReadKey();
            }
        }