using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VisimBox.Resources;
using System.Runtime.InteropServices;

namespace VisimBox.Renderer.Render2D
{
    public class FontManager : AbstractResMan<Font>
    {

        public FontManager() : base() { }

        /// <summary>
        /// Returns default font
        /// </summary>
        /// <returns></returns>
        public Font GetDefault()
        {
            if (resources.ContainsKey("default"))
                return resources["default"];

            //System.Drawing.Font def = new System.Drawing.Font("Courier", 10);
            System.Drawing.Font def = new System.Drawing.Font("Courier", 15, System.Drawing.FontStyle.Bold);
            return Add("default", def);
        }

        /// <summary>
        /// Adds new system font
        /// </summary>
        /// <param name="key"></param>
        /// <param name="sysfont"></param>
        /// <returns></returns>
        public Font Add(string key, System.Drawing.Font sysfont)
        {
            Font rval = new Font(sysfont);
            Add(key, rval);
            return rval;
        }

        /// <summary>
        /// Adds system font to manager and returns new rendering font
        /// </summary>
        /// <param name="sysfont">Valid System.Drawing.Font</param>
        /// <returns>Created font</returns>
        public Font Add(System.Drawing.Font sysfont)
        {
            string name = sysfont.Name + sysfont.Height.ToString();
            name = GetUniqueName(name);
            return Add(name, sysfont);
        }

        /// <summary>
        /// Ads font with required name and size to manager
        /// </summary>
        /// <param name="fontname">Name of the font</param>
        /// <param name="size"></param>
        /// <returns>Created font</returns>
        public Font Add(string fontname, int size)
        {
            string name = fontname + size.ToString();

            if (resources.ContainsKey(name))
                return resources[name];
            System.Drawing.Font sysfont = new System.Drawing.Font(fontname, (float)size);
            if (sysfont != null)
            {
                Font rval = Add(sysfont);
                sysfont.Dispose();
                return rval;
            }
            return AddFromFile(fontname, size);
        }

        /// <summary>
        /// Adds font from truetype file on disk
        /// </summary>
        /// <param name="fontfile">name of the file</param>
        /// <param name="size">Required size in pixels</param>
        /// <returns>Created font</returns>
        public Font AddFromFile(string fontfile, int size)
        {
            string name = fontfile + size.ToString();

            if (resources.ContainsKey(name))
                return resources[name];
            
            System.IO.Stream str = FileSystem.Instance.GetFile(fontfile);
            if (str == null)
            {
                throw new ArgumentException("Font file not found!");
            }

            System.Drawing.Font sysfont;

            var buffer = new byte[str.Length];
            str.Read(buffer, 0, buffer.Length);

            var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            try
            {
                var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);

                var fontCollection = new System.Drawing.Text.PrivateFontCollection();
                fontCollection.AddMemoryFont(ptr, buffer.Length);
                sysfont = new System.Drawing.Font(fontCollection.Families[0], (float)size);
            }
            catch (Exception ex)
            {
                throw new ArgumentException("Can't load font from file", ex);
            }
            finally
            {
                handle.Free();
            }
            Font rval = Add(name, sysfont);
            sysfont.Dispose();
            return rval;
        }

        //TODO: override of LOAD???
    }
}
