/*
 * Copyright (C) 2013 FooProject
 * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
using System;
using System.Collections.Generic;
using Windows.Graphics.Display;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using SharpDX;
using SharpDX.WIC;
using DXGI = SharpDX.DXGI;
using D2D = SharpDX.Direct2D1;
using D3D = SharpDX.Direct3D;
using D3D11 = SharpDX.Direct3D11;
using FooEditEngine.Metro;
using DotNetTextStore;
using DotNetTextStore.UnmanagedAPI.TSF;
using DotNetTextStore.UnmanagedAPI.WinDef;

namespace FooEditEngine
{
    class D2DPrintPreviewRender : D2DRenderBase,ITextRender,IPrintableTextRender
    {
        DXGI.Surface Surface;
        D3D11.Texture2D Texture;
        D2D.Device D2DDevice;
        D2D.DeviceContext D2DContext;
        D2D.Bitmap1 Bitmap;
        int dpi;
        Size Size;

        public D2DPrintPreviewRender(string fontName, double fontSize, Size size, uint dpi)
            : base()
        {
            this.Size = size;

            this.dpi = (int)dpi;

            base.ConstructRender = this.ConstructRenderHandler;
            base.ConstrctedResource = this.ConstructedResourceHandler;
            base.DestructRender = this.DestructRenderHandler;
            base.ReCreateTarget = this.ReCreateTargetHandler;
            base.GetDpi = this.GetDpi;
            base.ConstructDeviceResource(size.Width, size.Height);
            base.InitTextFormat(fontName, (float)fontSize);
        }

        new void GetDpi(out int dpix, out int dpiy)
        {
            dpix = this.dpi;
            dpiy = this.dpi;
        }

        public override void BeginDraw()
        {
            this.ReConstructDeviceResource(this.Size.Width,this.Size.Height);   //再構築しないとごみが残る
            base.BeginDraw();
        }

        public override void EndDraw()
        {
            throw new NotImplementedException();
        }

        public void EndDraw(IPrintPreviewDxgiPackageTarget target,uint page)
        {
            base.EndDraw();
            target.DrawPage(page, this.Surface.NativePointer, (float)this.dpi, (float)this.dpi);
        }

        public void SetScale(double scale)
        {
            this.D2DContext.Transform = Matrix3x2.Scaling((float)scale);
        }

        D2D.RenderTarget ConstructRenderHandler(D2D.Factory1 factory, D2D.RenderTargetProperties prop, double width, double height)
        {
            D3D11.Texture2DDescription desc = new D3D11.Texture2DDescription();
            desc.Width = (int)(width * dpi / 96);
            desc.Height = (int)(height * dpi / 96);
            desc.Format = DXGI.Format.B8G8R8A8_UNorm;
            desc.BindFlags = D3D11.BindFlags.RenderTarget | D3D11.BindFlags.ShaderResource;
            desc.ArraySize = 1;
            desc.MipLevels = 1;
            desc.Usage = D3D11.ResourceUsage.Default;
            desc.CpuAccessFlags = 0;
            desc.SampleDescription = new DXGI.SampleDescription(1, 0);
            this.Texture = new D3D11.Texture2D(base.D3DDevice, desc);

            this.Surface = this.Texture.QueryInterface<DXGI.Surface>();

            this.D2DDevice = new D2D.Device(factory, this.DXGIDevice);
            
            this.D2DContext = new D2D.DeviceContext(this.D2DDevice, D2D.DeviceContextOptions.None);

            this.D2DContext.DotsPerInch = new Size2F(this.dpi, this.dpi);

            D2D.BitmapProperties1 bmpProp = new D2D.BitmapProperties1();
            bmpProp.BitmapOptions = D2D.BitmapOptions.Target | D2D.BitmapOptions.CannotDraw;
            bmpProp.PixelFormat = new D2D.PixelFormat(DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Premultiplied);

            this.Bitmap = new D2D.Bitmap1(this.D2DContext, this.Surface, bmpProp);

            this.D2DContext.Target = this.Bitmap;

            return this.D2DContext;
        }

        void ConstructedResourceHandler()
        {
        }

        void DestructRenderHandler()
        {
            if (this.Texture != null)
                this.Texture.Dispose();
            if (this.Surface != null)
                this.Surface.Dispose();
            if (this.Bitmap != null)
                this.Bitmap.Dispose();
            if (this.D2DDevice != null)
                this.D2DDevice.Dispose();
            if (this.D2DContext != null)
                this.D2DContext.Dispose();
        }

        void ReCreateTargetHandler()
        {
        }

        public float HeaderHeight
        {
            get { return (float)this.emSize.Height; }
        }

        public float FooterHeight
        {
            get { return (float)this.emSize.Height; }
        }
    }
}
