<?php declare(strict_types = 1);

namespace SlevomatCodingStandard\Sniffs\ControlStructures;

use SlevomatCodingStandard\Sniffs\TestCase;

class JumpStatementsSpacingSniffTest extends TestCase
{

	public function testDefaultSettingsNoErrors(): void
	{
		$report = self::checkFile(__DIR__ . '/data/jumpStatementsSpacingWithDefaultSettingsNoErrors.php');
		self::assertNoSniffErrorInFile($report);
	}

	public function testDefaultSettingsErrors(): void
	{
		$report = self::checkFile(__DIR__ . '/data/jumpStatementsSpacingWithDefaultSettingsErrors.php');

		self::assertSame(29, $report->getErrorCount());

		self::assertSniffError(
			$report,
			10,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE,
			'Expected 1 line before "break", found 0.'
		);
		self::assertSniffError(
			$report,
			10,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 0 lines after "break", found 1.'
		);
		self::assertSniffError(
			$report,
			15,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTROL_STRUCTURE,
			'Expected 0 lines before "continue", found 1.'
		);
		self::assertSniffError(
			$report,
			15,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 0 lines after "continue", found 2.'
		);
		self::assertSniffError(
			$report,
			20,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTROL_STRUCTURE,
			'Expected 0 lines before "return", found 1.'
		);
		self::assertSniffError(
			$report,
			23,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTROL_STRUCTURE,
			'Expected 0 lines before "throw", found 1.'
		);
		self::assertSniffError(
			$report,
			23,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 0 lines after "throw", found 1.'
		);
		self::assertSniffError(
			$report,
			32,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE,
			'Expected 1 line before "goto", found 0.'
		);
		self::assertSniffError(
			$report,
			32,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_CONTROL_STRUCTURE,
			'Expected 1 line after "goto", found 2.'
		);
		self::assertSniffError(
			$report,
			37,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE,
			'Expected 1 line before "yield from", found 0.'
		);
		self::assertSniffError(
			$report,
			37,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 0 lines after "yield from", found 1.'
		);
		self::assertSniffError(
			$report,
			44,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTROL_STRUCTURE,
			'Expected 0 lines before "yield", found 1.'
		);
		self::assertSniffError(
			$report,
			44,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_CONTROL_STRUCTURE,
			'Expected 1 line after "yield", found 0.'
		);
		self::assertSniffError(
			$report,
			45,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE,
			'Expected 1 line before "return", found 0.'
		);
		self::assertSniffError(
			$report,
			45,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 0 lines after "return", found 2.'
		);
		self::assertSniffError(
			$report,
			49,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE,
			'Expected 1 line before "yield", found 0.'
		);
		self::assertSniffError(
			$report,
			49,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 0 lines after "yield", found 1.'
		);
		self::assertSniffError(
			$report,
			60,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE,
			'Expected 1 line before "return", found 0.'
		);
		self::assertSniffError(
			$report,
			67,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 0 lines after "break", found 1.'
		);
		self::assertSniffError(
			$report,
			77,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTROL_STRUCTURE,
			'Expected 0 lines before "return", found 1.'
		);
		self::assertSniffError(
			$report,
			82,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTROL_STRUCTURE,
			'Expected 0 lines before "return", found 1.'
		);
		self::assertSniffError(
			$report,
			91,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 0 lines after "return", found 1.'
		);
		self::assertSniffError(
			$report,
			108,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTROL_STRUCTURE,
			'Expected 0 lines before "return", found 1.'
		);
		self::assertSniffError(
			$report,
			108,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 0 lines after "return", found 1.'
		);
		self::assertSniffError(
			$report,
			126,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_CONTROL_STRUCTURE,
			'Expected 1 line after "yield", found 0.'
		);
		self::assertSniffError(
			$report,
			127,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE,
			'Expected 1 line before "return", found 0.'
		);
		self::assertSniffError(
			$report,
			127,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_CONTROL_STRUCTURE,
			'Expected 1 line after "return", found 0.'
		);
		self::assertSniffError(
			$report,
			128,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE,
			'Expected 1 line before "yield", found 0.'
		);
		self::assertSniffError(
			$report,
			139,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE,
			'Expected 1 line before "return", found 2.'
		);

		self::assertAllFixedInFile($report);
	}

	public function testModifiedSettingsNoErrors(): void
	{
		$report = self::checkFile(__DIR__ . '/data/jumpStatementsSpacingWithModifiedSettingsNoErrors.php', [
			'linesCountBefore' => 0,
			'linesCountBeforeFirst' => 1,
			'linesCountAfter' => 0,
			'linesCountAfterLast' => 3,
			'jumpStatements' => [
				'break',
				'continue',
				'return',
				'throw',
				'yield',
				'yield_from',
			],
		]);
		self::assertNoSniffErrorInFile($report);
	}

	public function testModifiedSettingsErrors(): void
	{
		$report = self::checkFile(__DIR__ . '/data/jumpStatementsSpacingWithModifiedSettingsErrors.php', [
			'linesCountBefore' => 0,
			'linesCountBeforeFirst' => 1,
			'linesCountAfter' => 0,
			'linesCountAfterLast' => 3,
			'jumpStatements' => [
				'break',
				'continue',
				'return',
				'throw',
				'yield',
				'yield_from',
			],
		]);
		self::assertSame(9, $report->getErrorCount());

		self::assertSniffError(
			$report,
			9,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 3 lines after "break", found 1.'
		);
		self::assertSniffError(
			$report,
			14,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 3 lines after "continue", found 0.'
		);
		self::assertSniffError(
			$report,
			17,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 3 lines after "return", found 1.'
		);
		self::assertSniffError(
			$report,
			40,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 3 lines after "yield from", found 1.'
		);
		self::assertSniffError(
			$report,
			48,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTROL_STRUCTURE,
			'Expected 1 line before "yield", found 2.'
		);
		self::assertSniffError(
			$report,
			48,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_CONTROL_STRUCTURE,
			'Expected 0 lines after "yield", found 2.'
		);
		self::assertSniffError(
			$report,
			51,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE,
			'Expected 0 lines before "return", found 2.'
		);
		self::assertSniffError(
			$report,
			51,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 3 lines after "return", found 2.'
		);
		self::assertSniffError(
			$report,
			55,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 3 lines after "yield", found 1.'
		);

		self::assertAllFixedInFile($report);
	}

	public function testAtTheEndOfFile(): void
	{
		$report = self::checkFile(__DIR__ . '/data/jumpStatementsSpacingAtTheEndOfFile.php');
		self::assertNoSniffErrorInFile($report);
	}

	public function testIgnoreWhenInCaseOrDefaultStatementNoErrors(): void
	{
		$report = self::checkFile(__DIR__ . '/data/jumpStatementsWhenInCaseOrDefaultNoErrors.php', [
			'linesCountBeforeWhenFirstInCaseOrDefault' => 0,
			'linesCountAfterWhenLastInCaseOrDefault' => 1,
			'linesCountAfterWhenLastInLastCaseOrDefault' => 0,
		]);
		self::assertNoSniffErrorInFile($report);
	}

	public function testWhenInCaseOrDefaultStatementErrors(): void
	{
		$report = self::checkFile(__DIR__ . '/data/jumpStatementsWhenInCaseOrDefaultErrors.php', [
			'linesCountBeforeWhenFirstInCaseOrDefault' => 0,
			'linesCountAfterWhenLastInCaseOrDefault' => 1,
			'linesCountAfterWhenLastInLastCaseOrDefault' => 0,
		]);

		self::assertSame(4, $report->getErrorCount());

		self::assertSniffError(
			$report,
			7,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTROL_STRUCTURE,
			'Expected 0 lines before "throw", found 1.'
		);
		self::assertSniffError(
			$report,
			7,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 1 line after "throw", found 0.'
		);
		self::assertSniffError(
			$report,
			17,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 1 line after "break", found 0.'
		);
		self::assertSniffError(
			$report,
			22,
			JumpStatementsSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE,
			'Expected 0 lines after "break", found 1.'
		);

		self::assertAllFixedInFile($report);
	}

	public function testThrowExpressionNoErrors(): void
	{
		$report = self::checkFile(__DIR__ . '/data/jumpStatementsThrowExpressionNoErrors.php');
		self::assertNoSniffErrorInFile($report);
	}

}
