package sane;

use strict; use warnings;

use Filter::Simple sub {
	my ($lines) = [split m/\n/, $_, -1];
	my $new_lines = sanify($lines);
	$_ = join "\n", @$new_lines, "";
};

our $new_lines;

sub sanify {
	my ($lines) = @_;
	my $tabs = [];
	my $spaces = [];
	for (@$lines) {
		my ($tab, $space) = m/ \A (\t*) (\s*)/x;
		push @$tabs, length($tab);
		push @$spaces, length($space);
	}

	$new_lines = [];

	sub out {
		push @$new_lines, join "", @_;
	}

	# a line at a time
	my $i = 0;
	while (defined $lines->[$i]) {
		my $line = $lines->[$i];
		my $tab = $tabs->[$i];
		my $space = $spaces->[$i];

		# handle multi-line quoted strings (q qq qx qr)
		my ($quote_block) = $line =~ s/ \b(q|qq|qx|qr)\z //x;
		if ($quote_block) {
			my $line_with_quote = $line;
			my $tab_strip = $tab + 1;
			++$i;
			my $quoted_lines = [];
			while (1) {
				$line = $lines->[$i];
				$tab = $tabs->[$i];
				$space = $spaces->[$i];
				if ($tab >= $tab_strip) {
					$line = substr $line, $tab_strip;
					push @$quoted_lines, $line;
				} else {
					last;
				}
			}
			if (@$quoted_lines == 0) {
				out($line_with_quote, "$quote_block", "{}");
			} else {
				out($line_with_quote);
				$quoted_lines->[0] = "$quote_block\{" . $quoted_lines->[0];
				$quoted_lines->[-1] .= "\\n";
				$line = pop @$quoted_lines;
				# last line is output by normal mech
				for (@$quoted_lines) { out($_); }
			}
		}

		# find number of next non-blank line
		# we need to compare indent of adjacent lines to add braces
		my $j = $i + 1;
		until (!defined $lines->[$j] || $lines->[$j] =~ m/\S/) { ++$j }

		my $line_next = $lines->[$j];
		if (!defined $line_next) { $line_next = ""; }
		my $tab_next = $tabs->[$j] || 0;
		my $space_next = $spaces->[$j] || 0;


	qq
		hello
		
		world

		# add parens for if, elsif, unless, while, until, for
		#   unless already has a ) at end of line
		#   XXX may be dodgy
		$line =~ s/ \A (\t*) (if|unless|while|until|for|\s+elsif)
		               (\s*) (.*) ([^)]) \z
			  /$1$2$3($4$5)/x;

		# add semicolons and braces

		if ($line =~ m/ \A \s* \z /x) {
			# don't change blank lines
		} elsif ($tab_next == $tab) {
			if ($space_next == 0) { $line .= ";"; }
		} elsif ($tab_next > $tab) {
			$line .= " " . "{" x ($tab_next - $tab);
		} elsif ($tab_next < $tab) {
			$line .= ";";
			my $d = $tab - $tab_next;
			if ($d > 1) {
				$line .= " };" x ($d-1);
			}
			$line .= " }";
			if ($space_next == 0) { $line .= ";"; }
		}
		
		out "$line";

		$i = $j; # go to next line
	}

	# add standard boilerplate
	$new_lines->[0]
		= "use strict; use warnings; use Perl6::Say; "
		  . ($new_lines->[0] || "");

	return $new_lines;
}

1;
