<?php declare(strict_types=1);

namespace Phan\Output\Printer;

use AssertionError;
use Phan\Issue;
use Phan\IssueInstance;
use Phan\Output\BufferedPrinterInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * This will print an issue as CSVs (Comma Separated Values) to the configured OutputInterface.
 */
final class CSVPrinter implements BufferedPrinterInterface
{

    /** @var OutputInterface for writing comma separated values to */
    private $output;

    /** @var resource in-memory stream for fputcsv() */
    private $stream;

    /** @param IssueInstance $instance */
    public function print(IssueInstance $instance)
    {
        \fputcsv($this->stream, [
            $instance->getFile(),
            $instance->getLine(),
            $instance->getIssue()->getSeverity(),
            $instance->getIssue()->getSeverityName(),
            Issue::getNameForCategory($instance->getIssue()->getCategory()),
            $instance->getIssue()->getType(),
            $instance->getMessageAndMaybeSuggestion(),
        ]);
    }

    /** flush printer buffer */
    public function flush()
    {
        \fseek($this->stream, 0);
        $contents = \stream_get_contents($this->stream);
        if (!\is_string($contents)) {
            throw new AssertionError("Failed to read in-memory csv stream");
        }
        $this->output->write($contents);
        \fclose($this->stream);
        $this->initStream();
    }

    /**
     * @param OutputInterface $output
     */
    public function configureOutput(OutputInterface $output)
    {
        $this->output = $output;
        $this->initStream();
    }

    private function initStream()
    {
        // Because fputcsv works on file pointers we need to do a bit
        // of dancing around with a memory stream.
        $stream = \fopen("php://memory", "rw");
        if (!\is_resource($stream)) {
            throw new AssertionError('php://memory should always be openable');
        }
        $this->stream = $stream;
        \fputcsv($this->stream, [
            "filename", "line", "severity_ord", "severity_name",
            "category", "check_name", "message"
        ]);
    }
}
