using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Diagnostics;
using System.Windows.Forms;

namespace Launcheroid
{
    public static class Launcher
    {
        public static string FILE_NAME = "links.lrd";
        private const string FILE_HEAD = "LnkrLnchr";
        public static string title = "Launcheroid "+Program.version;

        private static List<lLink> links = new List<lLink>();

        public static void Clear()
        {
            links.Clear();
        }

        public static void Add(string path)
        {
            lLink lnk = lLink.FromExternalFile(path);
            if (lnk == null)
                return;
            links.Add(lnk);
        }

        public static void Del(lLink item)
        {
            links.Remove(item);
        }

        #region Load/Save
        public static void Save()
        {
            FileStream fs = new FileStream(FILE_NAME, FileMode.Create, FileAccess.Write);
            BinaryWriter bw = new BinaryWriter(fs);
            bw.Write(Encoding.ASCII.GetBytes(FILE_HEAD));
            bw.Write((byte)2);
            bw.Write(title);
            bw.Write(links.Count);
            foreach (lLink lnk in links)
                lnk.SaveToStream(bw);
            bw.Close();
            fs.Close();
        }

        public static void Load()
        {
            Clear();
            if (!File.Exists(FILE_NAME))
                return;
            FileStream fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            try
            {
                if (Encoding.ASCII.GetString(br.ReadBytes(FILE_HEAD.Length)) != FILE_HEAD)
                    throw new Exception("El archivo no es compatible");
                int version=br.ReadByte();
                if (version > 2)
                    throw new Exception("Versión del archivo no soportada");
                title = br.ReadString();
                int cnt = br.ReadInt32();
                for (int i = 0; i < cnt; i++)
                    links.Add(lLink.FromStream(br,version));
            }
            finally
            {
                br.Close();
                fs.Close();
            }
        }

        public static void Navigate(string path)
        {
            try
            {
                string[] dirs=Directory.GetDirectories(path);
                string[] fils = Directory.GetFiles(path);
                foreach (string dir in dirs)
                    links.Add(lLink.FromExternalFile(dir));
                foreach (string fil in fils)
                    links.Add(lLink.FromExternalFile(fil));
            }
            catch { };
        }
        #endregion

        public static lLink[] Links { get { return links.ToArray(); } }
    }

    public class lLink
    {
        private string name;
        private string path;
        private string args;
        private Bitmap bmp;
        public bool Navigate;
        private string dir;

        #region Constructors
        private lLink()
        {
        }

        public static lLink FromExternalFile(string path)
        {
            lLink result = new lLink();
            result.path = path;
            result.name = System.IO.Path.GetFileNameWithoutExtension(path);
            if (result.name.Length > 20)
                result.name = result.name.Substring(0, 20 - 3) + "...";
            result.args = "";
            result.dir = System.IO.Path.GetDirectoryName(path);
            if (result.dir == null)
                result.dir = "";
            result.bmp = IconTool.GetFileJumbo(path);
            result.Navigate = Directory.Exists(path);
            return result;
        }

        public static lLink FromStream(BinaryReader br,int version)
        {
            lLink result = new lLink();
            switch (version)
            {
                case 0:
                    result.LoadFromStreamV0(br);
                    break;
                case 1:
                    result.LoadFromStreamV1(br);
                    break;
                case 2:
                    result.LoadFromStream(br);
                    break;
                default:
                    throw new Exception("Versión "+version+" no implementada");
            }
            return result;
        }
        #endregion

        #region Disk I/O
        internal void SaveToStream(BinaryWriter bw)
        {
            bw.Write(name);
            bw.Write(path);
            bw.Write(args);
            bw.Write(dir);
            bw.Write(Navigate);
            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, ImageFormat.Png);
            ms.Close();
            byte[] idata = ms.ToArray();
            ms = null;
            bw.Write(idata.Length);
            bw.Write(idata);
        }

        internal void LoadFromStreamV0(BinaryReader br)
        {
            name = br.ReadString();
            path = br.ReadString();
            args = br.ReadString();
            dir = "";
            Navigate = false;
            byte[] idata = br.ReadBytes(br.ReadInt32());
            MemoryStream ms = new MemoryStream(idata);
            bmp =(Bitmap) Bitmap.FromStream(ms);
        }

        internal void LoadFromStreamV1(BinaryReader br)
        {
            name = br.ReadString();
            path = br.ReadString();
            args = br.ReadString();
            dir = System.IO.Path.GetDirectoryName(path);
            if (dir == null)
                dir = "";
            Navigate = br.ReadBoolean();
            byte[] idata = br.ReadBytes(br.ReadInt32());
            MemoryStream ms = new MemoryStream(idata);
            bmp = (Bitmap)Bitmap.FromStream(ms);
        }

        internal void LoadFromStream(BinaryReader br)
        {
            name = br.ReadString();
            path = br.ReadString();
            args = br.ReadString();
            dir = br.ReadString();
            Navigate = br.ReadBoolean();
            byte[] idata = br.ReadBytes(br.ReadInt32());
            MemoryStream ms = new MemoryStream(idata);
            bmp = (Bitmap)Bitmap.FromStream(ms);
        }
        #endregion

        #region Launch
        public bool Open()
        {
            try
            {
                if (Navigate)
                    Process.Start(Program.path, "nav \"" + path + "\"");
                else
                {
                    ProcessStartInfo psi = new ProcessStartInfo();
                    psi.FileName = path;
                    psi.Arguments = args;
                    psi.ErrorDialog = true;
                    psi.WorkingDirectory = dir;
                    Process.Start(psi);
                }
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, e.GetType().Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            return false;
        }
        #endregion

        public Bitmap Icon { get { return bmp; } set { bmp = value; } }
        public string Name { get { return name; } set { name = value; } }
        public string Path { get { return path; } set { path = value; } }
        public string Args { get { return args; } set { args = value; } }
        public string Dir { get { return dir; } set { dir = value; } }
    }

}
