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

namespace ReportGeneration.Generators.LatexInclude;

public class LatexIncludeDocumentGenerator : DocumentGeneratorBase
{
  private const string figDir = "figures";
  private string? _lastHeading;

  public string Dir { get; }

  public LatexIncludeDocumentGenerator(string name, bool overwrite = false)
    : this(PrepareDir(name, overwrite))
  {
  }

  private LatexIncludeDocumentGenerator(string dir) : base($"{dir}/main.tex") => Dir = dir;

  private static string PrepareDir(string dirName, bool overwrite)
  {
    if (Directory.Exists(dirName))
    {
      if (overwrite)
      {
        Directory.Delete(dirName, true);
      }
      else
      {
        throw new InvalidOperationException($"Directory '{dirName}' already exists!");
      }
    }

    Directory.CreateDirectory(Path.Join(dirName, figDir));
    return dirName;
  }

  #region Writing

  /// <inheritdoc />
  public override IDocumentGenerator AppendHeading(int level, string text)
  {
    _lastHeading = text;

    return AppendParagraph((level) switch
    {
      1 => $"\\chapter{{{text}}}",
      2 => $"\\section{{{text}}}",
      3 => $"\\subsection{{{text}}}",
      4 => $"\\subsubsection{{{text}}}",
      5 => $"\\subsubsubsection{{{text}}}",
      _ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
    });
  }

  /// <inheritdoc />
  public override IDocumentGenerator AppendTable(int columns, Action<ITableGenerator> table)
  {
    string path;
    var figCnt = 0;

    do
    {
      path = Path.Join(Dir, figDir, $"fig_{_lastHeading}_{++figCnt}.tex");
    } while (File.Exists(path));

    using var file = File.Open(path, FileMode.CreateNew);
    using var writer = new LatexIncludeTableGenerator(columns, file);
    writer.Open();
    table(writer);
    writer.Close();
    
    AppendParagraph($"\\include{{{path}}}");
    return this;
  }

  /// <inheritdoc />
  public override IDocumentGenerator AppendParagraph(string? text = default)
  {
    AppendLine(text);
    AppendLine();
    return this;
  }

  #endregion

  public override string FormatImage(string path, IBounds? bounds = default) => @$"
\begin{{figure}}[ht]
  \centering
  \fbox{{\includegraphics[width=.7\textwidth]{{{path}}}}}
\end{{figure}}";
}