using Hotline.Share.Dtos.ExportWord;
using Hotline.Share.Enums.ExportWord;
using JiebaNet.Segmenter.Common;
using System.Reflection;

namespace Hotline.Application.ExportWord
{
    public static class IWordExportTemplateExtensions
    {
        public static IEnumerable<PlaceholderEntity> GetReplacements<T>(this T wordData) where T : IWordExportTemplate
        {
            List<PlaceholderEntity> list = new List<PlaceholderEntity>();
            PropertyInfo[] properties = typeof(T).GetProperties();
            foreach (PropertyInfo propertyInfo in properties)
            {
                PlaceholderEntity placeholderEntity = new PlaceholderEntity();
                string placeholder = (propertyInfo.IsDefined(typeof(PlaceholderAttribute)) ? propertyInfo.GetCustomAttribute<PlaceholderAttribute>().Placeholder.ToString() : ("{" + propertyInfo.Name + "}"));
                if (propertyInfo.PropertyType == typeof(string))
                {
                    placeholderEntity.Placeholder = placeholder;
                    placeholderEntity.PlaceholderType = EPlaceholderType.Text;
                    placeholderEntity.Data = new ExportText
                    {
                        Data = propertyInfo.GetValue(wordData)?.ToString()
                    };
                    list.Add(placeholderEntity);
                }
                else if (propertyInfo.PropertyType == typeof(ExportTable))
                {
                    placeholderEntity.Placeholder = placeholder;
                    placeholderEntity.PlaceholderType = EPlaceholderType.Table;
                    placeholderEntity.Data = (IWordElement)propertyInfo.GetValue(wordData);
                    list.Add(placeholderEntity);
                }
                else if (propertyInfo.PropertyType == typeof(ExportPicture))
                {
                    placeholderEntity.Placeholder = placeholder;
                    placeholderEntity.PlaceholderType = EPlaceholderType.Picture;
                    ExportPicture item = (ExportPicture)propertyInfo.GetValue(wordData);
                    placeholderEntity.Pictures = new List<ExportPicture> { item };
                    list.Add(placeholderEntity);
                }
                else if (typeof(IEnumerable<ExportPicture>).IsAssignableFrom(propertyInfo.PropertyType))
                {
                    placeholderEntity.Placeholder = placeholder;
                    placeholderEntity.PlaceholderType = EPlaceholderType.Picture;
                    IEnumerable<ExportPicture> pictures = (IEnumerable<ExportPicture>)propertyInfo.GetValue(wordData);
                    placeholderEntity.Pictures = pictures;
                    list.Add(placeholderEntity);
                }
                else if (propertyInfo.PropertyType == typeof(ExportParagraph))
                {
                    placeholderEntity.Placeholder = placeholder;
                    placeholderEntity.PlaceholderType = EPlaceholderType.Paragraph;
                    placeholderEntity.Data = (IWordElement)propertyInfo.GetValue(wordData);
                    list.Add(placeholderEntity);
                }
                else if (propertyInfo.PropertyType == typeof(ExportComplex))
                {
                    placeholderEntity.Placeholder = placeholder;
                    placeholderEntity.PlaceholderType = EPlaceholderType.Complex;
                    placeholderEntity.Data = (IWordElement)propertyInfo.GetValue(wordData);
                    list.Add(placeholderEntity);
                }
            }

            return list;
        }

        public static string RenderHtml(this ReportDto reportDto)
        {
            var body = string.Empty;
            if (reportDto != null)
            {
                var content = string.Empty;
                content = CreateTitle(reportDto.Title, content);
                content = CreateSubTitles(reportDto, content);
                content = CreateParagraphes(reportDto, content);
                content = CreateAttachments(reportDto, content);
                content = CreateBottoms(reportDto, content);
                body = $"<body style=\"{reportDto.CssStyle}\">{content}</body>";
            }
            var result = $"<html>{body}</html>";

            return result;
        }

        #region 渲染HTML
        private static string CreateBottoms(ReportDto reportDto, string content)
        {
            if (reportDto.BottomDtos != null && reportDto.BottomDtos.Any())
            {
                reportDto.BottomDtos.OrderBy(x => x.SortIndex).ToList().ForEach(item =>
                {

                    content = CreateBottoms(item, content);
                });
            }

            return content;
        }

        private static string CreateAttachments(ReportDto reportDto, string content)
        {
            if (reportDto.AttachmentDtos != null && reportDto.AttachmentDtos.Any())
            {
                var attachments = string.Empty;
                reportDto.AttachmentDtos.ForEach(item =>
                {
                    var attachment = string.Empty;
                    if (item.Title != null)
                    {
                        attachment = $"<div style=\"{item.Title.CssStyle}\">{item.Title.Content}</div>";
                    }

                    if (item.SubTitleDtos != null && item.SubTitleDtos.Any())
                    {
                        item.SubTitleDtos.ForEach(sub =>
                        {
                            attachment = CreateSubTitle(sub, attachment);
                        });
                    }

                    if (item.TableDtos != null && item.TableDtos.Any())
                    {
                        item.TableDtos.ForEach(tab =>
                        {
                            var body = $"";
                            var head = $"";
                            if (tab.HeadDto != null)
                            {
                                tab.HeadDto.RowDtos.ForEach(row =>
                                {
                                    string rowStr = CreateRow(row);

                                    head += rowStr;
                                });

                                head = $"<thead style=\"{tab.HeadDto.CssStyle}\">{head}</thead>";
                            }

                            if (tab.BodyDto != null)
                            {
                                tab.BodyDto.RowDtos.ForEach(row =>
                                {
                                    string rowStr = CreateRow(row);

                                    body += rowStr;
                                });

                                body = $"<tbody style=\"{tab.BodyDto.CssStyle}\">{body}</tbody>";
                            }

                            var table = $"<div style=\"float: left;width: 100%; margin-bottom: 10px;\"><table style=\"{tab.CssStyle}\">{head}{body}</table></div>";

                            attachment += table;
                        });
                    }

                    attachments += attachment;
                });
                content += attachments;
            }

            return content;
        }

        private static string CreateRow(RowDto row)
        {
            var colStr = $"";
            row.ColumnDtos.ForEach(col =>
            {
                colStr += $"<td style=\"{col.CssStyle}\">{col.Content}</td>";
            });
            var rowStr = $"<tr style=\"{row.CssStyle}\">{colStr}</tr>";
            return rowStr;
        }

        private static string CreateParagraphes(ReportDto reportDto, string content)
        {
            if (reportDto.ContentDto != null)
            {
                if(reportDto.ContentDto.TitleDto != null)
                {
                    content = CreateTitle(reportDto.ContentDto.TitleDto, content);
                }

                var paragraphes = string.Empty;

                if (reportDto.ContentDto.ParagraphDtos != null && reportDto.ContentDto.ParagraphDtos.Any())
                {
                    reportDto.ContentDto.ParagraphDtos.OrderBy(x => x.SortIndex).ToList().ForEach(item =>
                    {
                        var paragraph = string.Empty;
                        if (item.titleDto != null)
                        {
                            paragraph = $"<p style=\"{item.titleDto.CssStyle}\">{item.titleDto.Content}</p>";
                        }
                        if (item.Content.IsNotEmpty())
                        {
                            paragraph += $"<p style=\"{item.CssStyle}\">{item.Content}</p>";
                        }
                        paragraphes += paragraph;
                    });
                }

                content += $"<div style=\"{reportDto.ContentDto.CssStyle}\">{paragraphes}</div>";
            }

            return content;
        }

        private static string CreateSubTitles(ReportDto reportDto, string content)
        {
            if (reportDto.SubTitleDtos != null && reportDto.SubTitleDtos.Any())
            {
                reportDto.SubTitleDtos.OrderBy(x => x.SortIndex).ToList().ForEach(item =>
                {
                    content = CreateSubTitle(item, content);

                });
            }

            return content;
        }

        private static string CreateSubTitle(SubTitleDto subTitleDto, string content)
        {
            var children = string.Empty;

            if (subTitleDto.Children != null && subTitleDto.Children.Any())
            {
                subTitleDto.Children.OrderBy(x => x.SortIndex).ToList().ForEach(item =>
                {
                    children = CreateSubTitle(item, children);
                });
            }
            else if (subTitleDto.Content.IsNotEmpty())
            {
                children = subTitleDto.Content;
            }
            else
            {
                return content;
            }

            content += $"<div style=\"{subTitleDto.CssStyle}\">{children}</div>";

            return content;
        }

        private static string CreateBottoms(BaseReportDto baseReportDto, string content)
        {
            var children = string.Empty;

            if (baseReportDto.Children != null && baseReportDto.Children.Any())
            {
                baseReportDto.Children.OrderBy(x => x.SortIndex).ToList().ForEach(item =>
                {
                    children = CreateBottoms(item, children);
                });
            }
            else if (baseReportDto.Content.IsNotEmpty())
            {
                children = baseReportDto.Content;
            }
            else
            {
                return content;
            }

            content += $"<div style=\"{baseReportDto.CssStyle}\">{children}</div>";

            return content;
        }


        private static string CreateTitle(TitleDto titleDto, string content)
        {
            if (titleDto != null)
            {
                content += $"<div style=\"{titleDto.CssStyle}\">{titleDto.Content}</div>";
            }

            return content;
        }
        #endregion
    }
}
