using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.IO;
using System.Text;
using System.Windows.Forms;
using StarEngine;
using Ruby;
using VALUE = System.Int32;

namespace StarEngine.Ruby
{
    public partial class RubyInterpreter
    {
        private void InitializeFontClass()
        {
            VALUE cFont = SERubyConsts.ForName("Font");

            RUBY.rb_define_private_method(cFont, "__cs_initialize__",
                delegate(VALUE self, VALUE rbName, VALUE rbSize, VALUE rbStyles)
                {
                    RUBY.Send(self, "__cs_set_finalizer__");

                    float csSize = (float)RUBY.NUM2DBL(rbSize);
                    FontStyle csStyles = FontStyle.Regular;
                    if (RUBY.ToBool(RUBY.HashAref(rbStyles, "bold")))
                        csStyles |= FontStyle.Bold;
                    if (RUBY.ToBool(RUBY.HashAref(rbStyles, "italic")))
                        csStyles |= FontStyle.Italic;

                    FontFamily csFontFamily;
                    string csName = RUBY.StringValuePtr(rbName);
                    string csFullPath = PathExtensions.GetFullPathAndExtension(csName);
                    if (!FontExists(csName))
                    {
                        RUBY.rb_raise(SERubyConsts.ForName("::Errno::ENOENT"), csName);
                        return RUBY.Qnil;
                    }
                    try
                    {
                        if (File.Exists(csFullPath))
                        {
                            PrivateFontCollection pfc = new PrivateFontCollection();
                            pfc.AddFontFile(csFullPath);
                            csFontFamily = pfc.Families[0];
                        }
                        else
                        {
                            csFontFamily = new FontFamily(csName);
                        }
                    }
                    catch (FileNotFoundException)
                    {
                        RUBY.rb_raise(SERubyConsts.ForName("StarEngineError"), "invalid font file");
                        return RUBY.Qnil;
                    }

                    Font csFont = new Font(csFontFamily, csSize, csStyles, GraphicsUnit.Pixel);

                    RUBY.rb_iv_set(self, "@size", RUBY.rb_float_new(csFont.Size));
                    RUBY.rb_iv_set(self, "@name", RUBY.rb_str_new2(csFont.Name));
                    RUBY.rb_iv_set(self, "@bold", csFont.Bold ? RUBY.Qtrue : RUBY.Qfalse);
                    RUBY.rb_iv_set(self, "@italic", csFont.Italic ? RUBY.Qtrue : RUBY.Qfalse);

                    this.AddCachedObject(self, csFont);
                    return RUBY.Qnil;
                });

            RUBY.rb_define_method(cFont, "get_size",
                delegate(VALUE self, VALUE rbText)
                {
                    Font csFont = this.GetCachedObject<Font>(self);
                    string csText = RUBY.StringValuePtr(rbText);
                    csText = csText.Replace('\r', ' ').Replace('\n', ' ').Replace('\t', ' ').Replace(' ', '\u00a0');

                    VALUE rbArray = RUBY.rb_ary_new();

                    using (Bitmap b = new Bitmap(1, 1))
                    using (Graphics g = Graphics.FromImage(b))
                    {
                        StringFormat sf = StringFormat.GenericTypographic;
                        SizeF csSizeF = g.MeasureString(csText, csFont, int.MaxValue, sf);
                        Size csSize = Size.Ceiling(csSizeF);
                        RUBY.rb_ary_push(rbArray, RUBY.INT2NUM(csSize.Width));
                        RUBY.rb_ary_push(rbArray, RUBY.INT2NUM(csSize.Height));
                    }
                    return rbArray;
                });

            RUBY.rb_define_singleton_method(cFont, "exist?",
                 delegate(VALUE self, VALUE rbName)
                 {
                     string csName = RUBY.StringValuePtr(rbName);
                     return FontExists(csName) ? RUBY.Qtrue : RUBY.Qfalse;
                 });
        }

        private static bool FontExists(string nameOrPath)
        {
            InstalledFontCollection ifc = new InstalledFontCollection();
            if (Array.Exists(ifc.Families, delegate(FontFamily ff)
            {
                return ff.Name == nameOrPath;
            }))
                return true;

            string fullPath = PathExtensions.GetFullPathAndExtension(nameOrPath);
            return File.Exists(fullPath);
        }
    }
}
