using ReportGeneration.Abstract;
using ReportGeneration.Interface;
using System.IO;
using System.Reflection;
using System.Text;

namespace ReportGeneration.Generators;

public class HtmlDocumentGenerator : SubItemDocumentGeneratorBase
{
  private int _sectionLevel = 0;

  public string Title { get; init; } = string.Empty;

  /// <inheritdoc />
  public HtmlDocumentGenerator() { }

  /// <inheritdoc />
  public HtmlDocumentGenerator(string filePath) : base(filePath)
  {
    Title = Path.GetFileNameWithoutExtension(filePath);
  }

  /// <inheritdoc />
  public HtmlDocumentGenerator(Stream stream) : base(stream) { }

  /// <inheritdoc />
  public HtmlDocumentGenerator(Stream stream, Encoding encoding) : base(stream, encoding) { }

  #region State

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

    // Init html document
    Write("<!DOCTYPE html>");
    Write("<html>");

    // Header
    Write("<head>");
    Write(HtmlTools.Wrap("title", Title));
    Write("<meta charset=\"utf-8\">");
    Write("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
    Write("<style>");

    using (var stream = Resources.Get("Style.css"))
    {
      using var streamReader = new StreamReader(stream);
      Write(streamReader);
    }

    Write("</style>");
    Write("</head>");

    // Init body
    Write("<body>");
  }

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

    // End document
    Write("</body>");
    Write("</html>");
  }

  #endregion

  #region Writing

  /// <inheritdoc cref="AppendParagraph(string)" />
  public IDocumentGenerator AppendParagraph(string? text, string? @class) =>
    Append(HtmlTools.Wrap("p", text, @class));

  /// <inheritdoc />
  public override IDocumentGenerator AppendParagraph(string? text = default) =>
    AppendParagraph(text, default);

  /// <inheritdoc />
  public override IDocumentGenerator AppendHeading(int level, string text) =>
    Append($"<h{level} id=\"{text}\">{text}</h{level}>");

  /// <inheritdoc />
  protected override ITableGenerator MakeTable(int columns, Stream stream) =>
    new CollapsibleHtmlTableGenerator(columns, stream);

  /// <inheritdoc />
  public override string FormatImage(string path, IBounds? bounds = default) =>
    FormatImage(path, default, bounds);

  /// <inheritdoc cref="FormatImage(string,IBounds)" />
  public string FormatImage(string path, string? @class, IBounds? bounds = default) =>
    HtmlTools.FormatImage(path, @class, bounds);

  #endregion

  #region Resource Management

  private static class Resources
  {
    private static readonly Assembly assembly = Assembly.GetExecutingAssembly();

    private static readonly string basePath =
      typeof(HtmlDocumentGenerator).Namespace + ".Resources.";

    public static Stream Get(string fileName) =>
      assembly.GetManifestResourceStream(basePath + fileName) ??
      throw new FileNotFoundException("Could not get resource", fileName);
  }

  #endregion
}
