using System;
using System.IO;
using System.Media;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace XMP {
    /* Application Startup */
    internal static class Program {
        internal static void Main (string[] args) {
        }
    }

    /* Application Player System */
    internal static class Player {
        internal static SoundPlayer Service = null;
        internal static List<string> Files;
        internal static bool Loop = false;
        
        internal static bool Available {
            get {
                return Player.Service != null;
            }
        }

        internal static void Load (string[] paths) {
            foreach (string path in paths) {
                if (File.Exists(path))
                    Files.Add
            }
        }

        internal static void Play  ();
        internal static void Pause ();
        internal static void Stop  ();
        ...
    }

    /* Application Output System */
    internal static class Output {
        internal static string Tag = "XMP";
        internal static void Println (string content, ConsoleColor foreground) {
            ConsoleColor f = System.Console.ForegroundColor;
            System.Console.ForegroundColor = foreground;
            System.Console.WriteLine(content);
            System.Console.ForegroundColor = f;
        }
        internal static void Print (string content, ConsoleColor foreground) {
            ConsoleColor f = System.Console.ForegroundColor;
            System.Console.ForegroundColor = foreground;
            System.Console.Write(content);
            System.Console.ForegroundColor = f;
        }
        internal static void Error (string content) {
            Output.Print(String.Format("[{0}][ERR]: ", Output.Tag), ConsoleColor.Red);
            Output.Println(content, System.Console.ForegroundColor);
        }
        internal static void Warning (string content) {
            Output.Print(String.Format("[{0}][WAR]: ", Output.Tag), ConsoleColor.Yellow);
            Output.Println(content, System.Console.ForegroundColor);
        }
        internal static void Success (string content) {
            Output.Print(String.Format("[{0}][SUC]: ", Output.Tag), ConsoleColor.Green);
            Output.Println(content, System.Console.ForegroundColor);
        }
        internal static void Information (string content) {
            Output.Print(String.Format("[{0}][INF]: ", Output.Tag), ConsoleColor.Blue);
            Output.Println(content, System.Console.ForegroundColor);
        }
        internal static bool Confirm (string content) {
            Output.Print(String.Format("[{0}][{1}][Y\\All]: ", Output.Tag, content), ConsoleColor.Magenta);
            bool result = System.Console.ReadKey().Key == ConsoleKey.Y;
            System.Console.WriteLine();
            return result;
        }
        internal static string Ask (string content) {
            Output.Print(String.Format("[{0}][{1}][Y\\All]: ", Output.Tag, content), ConsoleColor.Magenta);
            return System.Console.ReadLine();
        }
        internal static void DrawBar ... (% bar cizer, 0-100 arasinda float deger alir. Math.Floor ile calisir)
    }
}