using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using FastReport.Export;
using FastReport.Utils;
using FastReport.Export.Html;
using System.Threading.Tasks;
using ImageFormat = System.Drawing.Imaging.ImageFormat;

namespace FastReport.Web.Blazor.Export
{
    public partial class BlazorExport : ExportBase
    {
        #region Private fields

        private readonly struct HTMLData
        {
            public readonly int PageNumber;
            public readonly int CurrentPage;
            public readonly ReportPage page;

            public HTMLData(int pageNumber, int curPage, ReportPage page)
            {
                PageNumber = pageNumber;
                CurrentPage = curPage;
                this.page = page;
            }
        }

        private int pagesCount;

        private ImageFormat imageFormat;
        private bool singlePage;
        private bool pictures;
        private bool embedPictures;
        private string? stylePrefix;
        private int prevStyleListIndex;
        private bool pageBreaks;
        private List<string> cssStyles;
        private string pageStyleName;

        private const string NBSP = "&nbsp;";
        private int currentPage = 0;
        private HTMLData d;
        private IGraphics htmlMeasureGraphics;
        private float maxWidth, maxHeight;
        private float leftMargin, topMargin;
        private bool enableMargins = false;

        #endregion Private fields

        #region Public properties

        //public RenderTreeBuilder globalBuilder;
        private RenderContext globalContext;


        /// <summary>
        /// Sets an onclick event handler
        /// </summary>
        public EventHandler<OnClickEventArgs> OnClick;

        /// <summary>
        /// Gets or sets images, embedded in html (hash:base64Image)
        /// </summary>
        public Dictionary<string, string> EmbeddedImages
        {
            get;
            set;
        }

        /// <summary>
        /// For internal use only.
        /// </summary>
        public string? StylePrefix
        {
            get { return stylePrefix; }
            set { stylePrefix = value; }
        }

        /// <summary>
        /// For internal use only.
        /// </summary>
        public string? WebImagePrefix
        {
            get;
            set;
        }

        /// <summary>
        /// For internal use only.
        /// </summary>
        public string? WebImageSuffix
        {
            get;
            set;
        }

        /// <summary>
        /// For internal use only.
        /// </summary>
        public List<BlazorPageData> PreparedPages { get; }

        /// <summary>
        /// Enable or disable the breaks between pages in print preview when single page mode is enabled
        /// </summary>
        public bool PageBreaks
        {
            get { return pageBreaks; }
            set { pageBreaks = value; }
        }

        /// <summary>
        /// Enable or disable the pictures in HTML export
        /// </summary>
        public bool Pictures
        {
            get { return pictures; }
            set { pictures = value; }
        }

        /// <summary>
        /// Enable or disable embedding pictures in HTML export
        /// </summary>
        public bool EmbedPictures
        {
            get { return embedPictures; }
            set { embedPictures = value; }
        }

        /// <summary>
        /// Enable or disable the single HTML page creation
        /// </summary>
        public bool SinglePage
        {
            get { return singlePage; }
            set { singlePage = value; }
        }

        /// <summary>
        /// Gets or sets the image format.
        /// </summary>
        public ImageFormat ImageFormat
        {
            get { return imageFormat; }
            set { imageFormat = value; }
        }

        /// <summary>
        /// Enable or disable margins for pages.
        /// </summary>
        public bool EnableMargins
        {
            get { return enableMargins; }
            set { enableMargins = value; }
        }

        #endregion Public properties

        #region Private methods

        private void ExportHTMLPageStart(int PageNumber, int CurrentPage)
        {
            PreparedPages[CurrentPage].PageNumber = PageNumber;
        }

        private void ExportHTMLPageFinal(in HTMLData d, float MaxWidth, float MaxHeight)
        {
            // CalcPageSize
            var page = PreparedPages[d.CurrentPage];
            page.Width = MaxWidth;
            page.Height = MaxHeight;
        }

        private void Init()
        {
            htmlMeasureGraphics = Report.MeasureGraphics;
            cssStyles = new List<string>();
            pagesCount = 0;
            prevStyleListIndex = 0;
            GeneratedStreams = new List<Stream>();
        }

        private void StartWeb()
        {
            PreparedPages.Clear();
            for (int i = 0; i < Report.PreparedPages.Count; i++)
                PreparedPages.Add(new BlazorPageData());
        }

        #endregion Private methods

        #region Protected methods

        /// <inheritdoc/>
        protected override void Start()
        {
            base.Start();

            Init();

            StartWeb();
        }

        /// <inheritdoc/>
        protected override void ExportPageBegin(ReportPage page)
        {
            pagesCount++;
            // Web
            ProcessPageBegin(CurPage, page);
        }

        /// <inheritdoc/>
        protected override void ExportPageEnd(ReportPage page)
        {
            // Web
            ProcessPageEnd();
        }

        public void Export(Report report, RenderTreeBuilder builder)
        {
            var context = new RenderContext(builder, OnClick);
            globalContext = context;
            Export(report, (Stream)null);
        }

        /// <summary>
        /// Process Page with number p and real page ReportPage
        /// </summary>
        /// <param name="p"></param>
        /// <param name="page"></param>
        public void ProcessPageBegin(int p, ReportPage page)
        {
            d = new HTMLData(pagesCount, p, page);
            ExportHTMLPageLayeredBegin(d);
        }

        /// <summary>
        /// Process Page with number p and real page ReportPage
        /// </summary>
        /// <param name="p"></param>
        /// <param name="ReportPage"></param>
        public void ProcessPageEnd()
        {
            ExportHTMLPageLayeredEnd(d);
        }

        #endregion Protected methods

        /// <inheritdoc/>
        public override void Serialize(FRWriter writer)
        {
            base.Serialize(writer);
            writer.WriteBool("Pictures", Pictures);
            writer.WriteBool("EmbedPictures", EmbedPictures);
            writer.WriteBool("SinglePage", SinglePage);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BlazorExport"/> class.
        /// </summary>
        public BlazorExport()
        {
            Zoom = 1.0f;
            HasMultipleFiles = true;
            pictures = true;
            singlePage = false;
            imageFormat = ImageFormat.Png;
            prevStyleListIndex = 0;
            pageBreaks = true;
            EmbeddedImages = new Dictionary<string, string>();

            // Init_WebMode
            ShowProgress = false;
            PreparedPages = new List<BlazorPageData>();
            OpenAfterExport = false;
        }
    }
}
