<?php
/**
 * @package   Essentials YOOtheme Pro 2.2.16 build 0813.1608
 * @author    ZOOlanders https://www.zoolanders.com
 * @copyright Copyright (C) Joolanders, SL
 * @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
 */

namespace ZOOlanders\YOOessentials\Form\Action\SaveCsv;

use YOOtheme\File;
use YOOtheme\Path;
use YOOtheme\Str;
use ZOOlanders\YOOessentials\Util;

trait InteractsWithCsv
{
    private static function resolveCsvPath(object $config): string
    {
        $file = $config->file ?? null;

        if (!$file) {
            throw new \RuntimeException('A path to a CSV file must be specified.');
        }

        if (!Str::startsWith($file, '~') && !Str::startsWith($file, '/')) {
            $file = "~/$file";
        }

        if (!File::exists($file) || !File::isFile($file)) {
            throw new \RuntimeException('The specified path is not a valid CSV file.');
        }

        return Path::resolve($file);
    }

    private static function readCsvHeader(object $config)
    {
        $filepath = self::resolveCsvPath($config);

        $separator = self::separator($config);
        $enclosure = self::enclosure($config);

        $handle = fopen($filepath, 'r');
        $header = fgetcsv($handle, null, $separator, $enclosure);

        fclose($handle);

        if (!$header) {
            throw new \RuntimeException('No columns found. At least one column has to be set in the header.');
        }

        $header = array_map(
            function (string $headerCell, int $index) {
                $headerCell = trim($headerCell);
                if (strlen($headerCell) === 0) {
                    throw new \RuntimeException(
                        sprintf('Column at position %s is missing a header. All columns must have a header.', ++$index)
                    );
                }

                return $headerCell;
            },
            $header,
            array_keys($header)
        );

        return $header;
    }

    private static function writeCsv(array $data, object $config): void
    {
        $filepath = self::resolveCsvPath($config);
        $separator = self::separator($config);
        $enclosure = self::enclosure($config);

        self::checkLastLineEnding($filepath);

        $handle = fopen($filepath, 'a+');

        fputcsv($handle, $data, $separator, $enclosure);
        fclose($handle);
    }

    private static function separator(object $config): string
    {
        return Util\Prop::parseString($config, 'separator', ',', 1);
    }

    private static function enclosure(object $config): string
    {
        return Util\Prop::parseString($config, 'enclosure', '"', 1);
    }

    private static function checkLastLineEnding(string $filepath): void
    {
        $file = fopen($filepath, 'r');
        fseek($file, -1, SEEK_END);

        $char = fgetc($file);

        if ($char === "\n" || $char === "\r") {
            return;
        }

        $file = fopen($filepath, 'a+');
        fwrite($file, "\n");
        fclose($file);
    }
}
