<?php

namespace Shellbox\Command;

use Shellbox\ShellboxError;

/**
 * Class representing the result of running a BoxedCommand
 */
class BoxedResult extends UnboxedResult {
	/**
	 * On the server and after local execution, the uploaded files are
	 * represented here as OutputFileToUrl objects. On the client, they are
	 * OutputFilePlaceholder objects.
	 *
	 * @var OutputFile[]
	 */
	private $files = [];

	/**
	 * Add an output file to the result
	 *
	 * @internal For use by BoxedExecutor
	 * @param string $name The file name relative to the working directory
	 * @param OutputFile $outputFile
	 */
	public function addOutputFile( $name, OutputFile $outputFile ) {
		$this->files[$name] = $outputFile;
	}

	/**
	 * Get the contents of an output file as a string
	 *
	 * @param string $name The file name relative to the working directory
	 * @return string|null The contents, or null if the command did not create
	 *   a file of that name, or if the output file was not registered in the
	 *   BoxedCommand.
	 */
	public function getFileContents( $name ) {
		if ( !isset( $this->files[$name] ) ) {
			return null;
		}
		$file = $this->files[$name];
		if ( $file instanceof OutputFileWithContents ) {
			return $file->getContents();
		} else {
			throw new ShellboxError(
				"Can't provide contents of a file that was sent to a server" );
		}
	}

	/**
	 * Query whether an output file was received. Files that are uploaded to a
	 * URL are not included in this.
	 *
	 * @param string $name
	 * @return bool
	 */
	public function wasReceived( $name ) {
		return isset( $this->files[$name] )
			&& ( $this->files[$name] instanceof OutputFileWithContents );
	}

	/**
	 * Query whether an output file was generated by the command
	 *
	 * @since 4.1.0
	 * @param string $name
	 * @return bool
	 */
	public function wasGenerated( $name ) {
		return isset( $this->files[$name] );
	}

	/**
	 * Get the names of all files which were registered and were created by the
	 * command.
	 *
	 * @return string[]
	 */
	public function getFileNames() {
		return array_keys( $this->files );
	}

	/**
	 * Get the names of all files which were received. This is all generated
	 * files except for uploaded files.
	 *
	 * @since 4.1.0
	 * @return string[]
	 */
	public function getReceivedFileNames() {
		$names = [];
		foreach ( $this->files as $name => $file ) {
			if ( $file instanceof OutputFileWithContents ) {
				$names[] = $name;
			}
		}
		return $names;
	}

	/**
	 * Get the names of all files which were uploaded.
	 *
	 * @since 4.1.0
	 * @return string[]
	 */
	public function getUploadedFileNames() {
		return array_diff( $this->getFileNames(), $this->getReceivedFileNames() );
	}
}
