/*
* Author:          Patrick-Christopher Mattulat
* Co-Author:       Claude Sonnet 4.6 (LLM)
* Company:         Lynar Studios
* E-Mail:          webmaster@lynarstudios.com
* Created:         2023-02-21
* Changed:         2026-06-24
*
* */

#include <ls-std/core/ConditionalFunctionExecutor.hpp>
#include <ls-std/core/exception/IllegalArgumentException.hpp>
#include <ls-std/io/FileReader.hpp>
#include <ls-std/io/NewLine.hpp>
#include <ls-std/io/evaluator/FileExistenceEvaluator.hpp>
#include <ls-std/io/section-pair/model/SectionPairDocument.hpp>
#include <ls-std/io/section-pair/reader/SectionPairFileReader.hpp>
#include <ls-std/io/section-pair/validator/SectionPairFileExtensionValidator.hpp>
#include <memory>

using ls::standard::core::Class;
using ls::standard::core::ConditionalFunctionExecutor;
using ls::standard::core::IllegalArgumentException;
using ls::standard::core::type::byte_field;
using ls::standard::io::File;
using ls::standard::io::FileExistenceEvaluator;
using ls::standard::io::FileReader;
using ls::standard::io::NewLine;
using ls::standard::io::SectionPairDocument;
using ls::standard::io::SectionPairFileExtensionValidator;
using ls::standard::io::SectionPairFileReader;
using ls::standard::io::SectionPairFileReaderParameter;
using std::make_shared;
using std::shared_ptr;
using std::string;

SectionPairFileReader::SectionPairFileReader(const SectionPairFileReaderParameter &_parameter) : Class("SectionPairFileReader"), parameter(_parameter)
{
  ConditionalFunctionExecutor{this->parameter.getFileExistenceEvaluator() == nullptr}.execute([this] { _createFileExistenceEvaluator(); });
  this->parameter.getFileExistenceEvaluator()->evaluate();
  this->_checkFileExtension();
  ConditionalFunctionExecutor{this->parameter.getReader() == nullptr}.execute([this] { _createReader(); });
  ConditionalFunctionExecutor{this->parameter.getDocument() == nullptr}.execute([this] { _createDocument(); });
}

SectionPairFileReader::~SectionPairFileReader() noexcept = default;

shared_ptr<SectionPairDocument> SectionPairFileReader::getDocument() const
{
  return this->parameter.getDocument();
}

byte_field SectionPairFileReader::read()
{
  this->parameter.getDocument()->clear();
  byte_field data = this->parameter.getReader()->read();
  this->parameter.getDocument()->reserveNewLine(SectionPairFileReader::_detectNewLine(data));
  this->parameter.getDocument()->unmarshal(data);

  return data;
}


void SectionPairFileReader::_checkFileExtension() const
{
  if (!SectionPairFileExtensionValidator{this->parameter.getFilePath()}.isValid())
  {
    const string message = "\"" + this->parameter.getFilePath() + "\" does not have a valid section pair file extension (.txt or .sp)!";
    throw IllegalArgumentException{message};
  }
}

void SectionPairFileReader::_createDocument()
{
  this->parameter.setDocument(make_shared<SectionPairDocument>());
}

void SectionPairFileReader::_createFileExistenceEvaluator()
{
  this->parameter.setFileExistenceEvaluator(make_shared<FileExistenceEvaluator>(this->parameter.getFilePath()));
}

void SectionPairFileReader::_createReader()
{
  File file{this->parameter.getFilePath()};
  this->parameter.setReader(make_shared<FileReader>(file));
}

string SectionPairFileReader::_detectNewLine(const byte_field &_data)
{
  return _data.find(NewLine::getWindowsNewLine()) != string::npos ? NewLine::getWindowsNewLine() : NewLine::getUnixNewLine();
}
