<?php

namespace DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Writer\XML;

use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\Collection\ProductFieldCollection;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\ProductFieldXml;
use DOMElement;
use DOMDocument;
use Exception;
abstract class AbstractBatchXmlWriter
{
    /**
     * @var ProductFieldCollection[]
     */
    protected array $batch = [];
    public function add_to_batch(ProductFieldCollection $product_fields): void
    {
        $this->batch[] = $product_fields;
    }
    public function flush_batch(string $file_path, bool $create_new_file): void
    {
        $items = $create_new_file ? $this->prepare_root_element() : $this->prepare_root_element_from_file($file_path);
        $dom = $items->ownerDocument;
        foreach ($this->batch as $product_fields) {
            $product = $dom->createElement($this->get_product_item_tag());
            foreach ($product_fields as $field) {
                if ($field instanceof ProductFieldXml) {
                    $field->map_xml_value($product);
                }
            }
            $items->appendChild($product);
        }
        $this->save_to_file($items, $file_path);
        $this->clear_batch();
    }
    public function has_batch(): bool
    {
        return !empty($this->batch);
    }
    public function get_batch_count(): int
    {
        return count($this->batch);
    }
    public function clear_batch(): void
    {
        $this->batch = [];
    }
    abstract protected function get_product_item_tag(): string;
    abstract protected function get_product_items_tag(): string;
    protected function prepare_root_element_from_file(string $path): DOMElement
    {
        $xml_document = new DOMDocument();
        $xml_document->formatOutput = \true;
        $xml_document->preserveWhiteSpace = \false;
        $xml_document->load($path);
        $items = $this->find_single_in_dom_tree($xml_document, '//' . $this->get_product_items_tag());
        return $items === \false ? $this->prepare_root_element() : $items;
    }
    protected function save_to_file(DOMElement $offers_xml_element, string $path): void
    {
        $offers_xml_element->ownerDocument->save($path);
    }
    protected function find_single_in_dom_tree(DOMDocument $xml_document, string $query): ?DOMElement
    {
        $xpath = new \DOMXPath($xml_document);
        $result = $xpath->query($query);
        if (isset($result[0])) {
            return $result[0];
        }
        return null;
    }
    abstract protected function prepare_root_element(): DOMElement;
}
