package Salus::Command;
use strict; use warnings;
use Salus;
use Rope;
use Rope::Autoload;
use feature qw/say/;
use Term::Table;
use Term::Size;
use JSON qw//;

prototyped (
	info => [qw/
		title help_title header_title header_descriptionr read_title read_desc 
		add_title add_desc all_title all_desc get_title get_desc get_col_title 
		get_col_desc set_title set_desc set_col_title set_col_desc delete_title 
		delete_desc delete_col_title delete_col_desc write_title write_desc exit_title exit_desc/
	],
	title => qq|Welcome to the command line interface for Salus\n|, 
	help_title => qq|The following are commands that can be used to manipulate a Salus CSV\n|,
	header_title => q|+ Headers|,
	header_description => qq|\tprint the headers of the csv - headers|,
	read_title => qq|+ Read File|,
	read_desc => qq|\tread a salus csv file - read \$filepath|,
	add_title => qq|+ Add Row|,
	add_desc => qq|\tadd a new row, the delimeter is a space not wrapped in quotations - add \$one \$two \$three|,
	all_title => qq|+ All|,
	all_desc => qq|\tprint all rows - all|,
	get_title => qq|+ Get Row|,
	get_desc => qq|\tretrieve a row by index and print it to the terminal - get \$index|,
	get_col_title => qq|+ Get Row Column|,
	get_col_desc => qq|\tretrieve a column by row and column index and print it to the terminal - get_col \$row \$col|,
	set_title => qq|+ Set Row|,
	set_desc => qq|\tset an existing row by index - set \$index|,
	set_col_title => qq|+ Set Row Column|,
	set_col_desc => qq|\tset a columns value by row and column index - set_col \$row \$col|,
	delete_title => qq|+ Delete Row|,
	delete_desc => qq|\tdelete a row by index - delete \$row|,
	delete_col_title => qq|+ Delete Row|,
	delete_col_desc => qq|\tdelete a column by row index and column index - delete \$row \$col|,
	write_title => qq|+ Write File|,
	write_desc => qq|\twrite data to a file - write \$filepath|,
	exit_title => qq|+ Exit|,
	exit_desc => qq|\tto exit you can either use - CTRL C -  or type - exit|,
	salus => undef
);

function INITIALISED => sub {
	my ($self, $params) = @_;	
	
	push @INC, $params->{lib} if $params->{lib};
	
	my $class = $params->{class};
	
	if ($class) {
		eval "require $class";
		$self->class = $class = $class->new();
	} else {
		if (!$params->{headers}) {
			say "No class or headers passed while starting the salus script";
			exit;
		}

		if (!ref $params->{headers}) {
			$params->{headers} = JSON->new->decode($params->{headers});
		}

		$self->class = $class = Salus->new({
			headers => $params->{headers}
		});
	}

	$self->salus = $class;
};

function run => sub {
	my ($self, $params) = @_;

	for (@{ $self->info }) {
		say $self->$_;
	}

	my $switch = $self->routes();

	while (1) {
		print "cmd: ";
		my $input = <STDIN>;
		chomp($input);
		if ($input eq 'exit') {
			exit;
		}
		my ($cmd, @args) = $self->extract_line_args($input);
		$self->$cmd(@args);		
	}
};

function read => sub {
	my ($self, $file) = @_;
	$self->salus->file = $file;
	$self->salus->read();
};

function write => sub {
	my ($self, $file) = @_;
	$self->salus->file = $file if $file;
	$self->salus->write();
};

function add => sub {
	my ($self, @row) = @_;
	$self->salus->add_row(\@row);
};

function all => sub {
	my ($self, $index) = @_;
	my @rows;
	for (@{$self->salus->rows}) {
		push @rows, $_->as_array;
	}
	$self->print_table(\@rows);
};

function get => sub {
	my ($self, $index) = @_;
	my $row = $self->salus->get_row($index);
	unless ($row) {
		say "No row available for index ${index}";
	 	return;
	}
	$self->print_table($row->as_array);
};

function get_col => sub {
	my ($self, $r, $c) = @_;
	$self->salus->set_row_col($r, $c);
};

function set => sub {
	my ($self, $r, @row) = @_;
	$self->salus->set_row($r, \@row);
};

function set_col => sub {
	my ($self, $r, $c, $v) = @_;
	$self->salus->set_row_col($r, $c, $v);
};

function delete => sub {
	my ($self, $row) = @_;
	$self->salus->delete_row($row);
};

function delete_col => sub {
	my ($self, $r, $c) = @_;
	$self->salus->delete_row_col($r, $c);
};

function extract_line_args => sub {
	my ($self, $line) = @_;
	my @array = map {
		my $m = $_;
		if ($m ne "") {
			$m =~ s/^("|')|("|')$//g;
			$m;
		} else {
			()
		}
	} split /\s*("[^"]+"|[^\s]+)/, $line;
	return @array;
};

function headers => sub {
	my ($self) = @_;
	$self->print_table();
};

function print_table => sub {
	my ($self, $rows) = @_;
	my ($columns, $r) = Term::Size::chars *STDOUT{IO};
	my $table = Term::Table->new(
		max_width      => $columns,
		pad            => 4,
		allow_overflow => 0,
		collapse       => 1,
		($rows ? (
			header => $self->salus->headers_stringify,
			rows   => ref $rows->[0] ? $rows : [
				$rows
			]
		) : (
			rows => [
				$self->salus->headers_stringify
			]
		))
	);
	say $_ for $table->render;
};

1;
