package Kephra::Document::Property;
our $VERSION = '0.04';

use strict;
use warnings;
# some internal shortcut helper
sub _ep_ref     { Kephra::Document::Data::_ep($_[0]) }
sub _doc_nr     { Kephra::Document::Data::valid_or_current_doc_nr($_[0]) }
sub _is_current { $_[0] == Kephra::Document::Data::current_nr() }
sub _get_attr   { Kephra::Document::Data::get_attribute(@_) }
sub _set_attr   { Kephra::Document::Data::set_attribute(@_) }
#
# general API for single and multiple values (getter/setter)
#
sub get {
	my $property = shift;
	my $doc_nr = _doc_nr(shift);
	return if $doc_nr < 0;
	if    (not ref $property)        { _get_attr($property, $doc_nr) }
	elsif (ref $property eq 'ARRAY') {
		my @result;
		push @result, _get_attr($_, $doc_nr) for @$property;
		\@result;
	}
}
sub _set{
	my ($key, $v) = @_;
	return unless defined $v;
	return set_codepage($v)  if $key eq 'codepage';
	return set_EOL_mode($v)  if $key eq 'EOL';
	return set_readonly($v)  if $key eq 'readonly';
	return set_syntaxmode($v)if $key eq 'syntaxmode';
	return set_tab_size($v)  if $key eq 'tab_size';
	return set_tab_mode($v)  if $key eq 'tab_use';
}
sub set {
	if (not ref $_[0] and defined $_[1]){_set(@_)}
	elsif ( ref $_[0] eq 'HASH')        {_set($_, $_[0]->{$_}) for keys %{$_[0]}}
}
sub get_file { _get_attr('file_path') }
sub set_file {
	my ($file, $nr) = @_;
	$nr = _doc_nr($nr);
	return if $nr < 0;
	Kephra::Document::Data::set_file_path($file, $nr);
	Kephra::App::TabBar::refresh_label($nr);
	Kephra::App::Window::refresh_title() if _is_current($nr);
}
#
# property specific API
#
#
# syntaxmode
sub get_syntaxmode { _get_attr('syntaxmode') }
sub set_syntaxmode { Kephra::Document::SyntaxMode::set(@_) }
#
#
sub get_codepage { _get_attr('codepage', $_[0]) }
sub set_codepage {
	my ($new_value, $doc_nr) = @_;
	$doc_nr = _doc_nr($doc_nr);
	return if $doc_nr < 0 or not defined $new_value;
	my $old_value = get_codepage($doc_nr);
	my $ep = _ep_ref($doc_nr);
	if    ($old_value eq 'ascii' and $new_value eq 'utf8'){
		#unless (Encode::is_utf8($ep->GetText())) {
			Kephra::Document::Data::update_attributes($doc_nr);
			eval {
				#Encode::encode('ascii');
				$ep->SetText( Encode::decode('utf8', $ep->GetText()) );
			};
			#print "$@\n";
			Kephra::Document::Data::evaluate_attributes($doc_nr);
		#}
		#print Encode::is_utf8($ep->GetText())."\n";
	}
	elsif ($old_value eq 'utf8' and $new_value eq 'ascii') {
		Kephra::Document::Data::update_attributes($doc_nr);
		$ep->SetText( Encode::encode('utf8', $ep->GetText()) );
		Kephra::Document::Data::evaluate_attributes($doc_nr);
	}
#print "ask auto $mode\n";
	#$ep->SetCodePage( &Wx::wxSTC_CP_UTF8 );
	_set_attr('codepage', $new_value, $doc_nr);
	Kephra::App::StatusBar::codepage_info($new_value);
}
sub switch_codepage {
	set_codepage( get_codepage( _doc_nr() ) eq 'utf8' ? 'ascii' : 'utf8' );
}
#
# tab size
sub get_tab_size { _get_attr('tab_size', $_[0]) }
sub set_tab_size {
	my ($size, $nr) = @_;
	$nr = _doc_nr($nr);
	return if not $size or $nr < 0;
	my $ep = _ep_ref();
	$ep->SetTabWidth($size);
	$ep->SetIndent($size);
	$ep->SetHighlightGuide($size);
	_set_attr('tab_size', $size, $nr);
}
#
# tab use
sub get_tab_mode { _get_attr('tab_use', $_[0]) }
sub set_tab_mode {
	my $mode = shift;
	my $nr = _doc_nr(shift);
	return if $nr < 0;
	my $ep = _ep_ref();
	if ($mode eq 'auto') {
		if ($ep->GetTextLength){
			my $line;
			for my $lnr (0 .. $ep->GetLineCount()-1){
				$line = $ep->GetLine($lnr);
				if ($line =~ /^( |\t)/) {
					$mode = $1 eq ' ' ? 0 : 1;
					last;
				}
			}
		}
		else {
			$mode = Kephra::File::_config()->{defaultsettings}{new}{tab_use};
		}
	}
	$ep->SetUseTabs($mode);
	_set_attr('tab_use', $mode, $nr);
	Kephra::App::StatusBar::tab_info() if _is_current($nr);
}
sub set_tabs_hard  { set_tab_mode(1) }
sub set_tabs_soft  { set_tab_mode(0) }
sub switch_tab_mode{ get_tab_mode() ? set_tab_mode(0) : set_tab_mode(1) }
#
# EOL
sub EOL_length   { _get_attr('EOL_length') }
sub get_EOL_mode { _get_attr('EOL') }
sub set_EOL_mode {
	my $mode = shift;
	return unless defined $mode;
	if ($mode eq 'OS') {
		if    (&Wx::wxMSW) {$mode = 'cr+lf'}
		elsif (&Wx::wxMAC) {$mode = 'cr'   }
		else               {$mode = 'lf'   }
	}
	$mode = detect_EOL_mode() if $mode eq 'auto';
	my $ep = _ep_ref();
	my $eoll = 1;
	if ( $mode eq 'cr+lf'or $mode eq 'win') {$ep->SetEOLMode(&Wx::wxSTC_EOL_CRLF); 
		$eoll = 2;
	}
	elsif ( $mode eq 'cr'or $mode eq 'mac') {$ep->SetEOLMode(&Wx::wxSTC_EOL_CR) }
	else                                    {$ep->SetEOLMode(&Wx::wxSTC_EOL_LF) } 
	_set_attr('EOL',        $mode);
	_set_attr('EOL_length', $eoll);
	Kephra::App::StatusBar::EOL_info($mode);
}

sub convert_EOL {
	my $mode  = shift || get_EOL_mode();
	my $doc_nr = _doc_nr(shift);
	my $ep = _ep_ref($doc_nr);
	$mode = Kephra::File::_config()->{defaultsettings}{EOL_open} unless $mode;
	$mode = detect_EOL_mode() if $mode eq 'auto';
	Kephra::EventTable::freeze_group('edit');
	if ($mode eq 'cr+lf' or $mode eq 'win')  {$ep->ConvertEOLs(&Wx::wxSTC_EOL_CRLF)}
	elsif ($mode eq 'cr' or $mode eq 'mac' ) {$ep->ConvertEOLs(&Wx::wxSTC_EOL_CR)}
	else                                     {$ep->ConvertEOLs(&Wx::wxSTC_EOL_LF)}
	Kephra::EventTable::thaw_group('edit');
	set_EOL_mode($mode);
}

sub detect_EOL_mode {
	my $ep = _ep_ref();
	my $end_pos   = $ep->PositionFromLine(1);
	my $begin_pos = $end_pos - 3;
	$begin_pos = 0 if $begin_pos < 0;
	my $text = $ep->GetTextRange( $begin_pos, $end_pos );

	if ( length($text) < 1 ) { return 'auto' }
	else {
#print "win \n" if $text =~ /\r\n/;
		#return 'cr+lf' if $text =~ /\r\n/;
		#return 'cr'    if $text =~ /\r/;
		#return 'lf'    if $text =~ /\n/;
		return 'auto';
	}
}
#
# write protection
sub get_readonly { _get_attr('readonly') }
sub set_readonly {
	my $status = shift;
	my $ep     = _ep_ref();
	if (not $status or $status eq 'off' ) {
			$ep->SetReadOnly(0);
			$status = 'off';
	} elsif ( $status eq 'on' or $status eq '1' ) {
		$ep->SetReadOnly(1);
		$status = 'on';
	} elsif ( $status eq 'protect' or $status eq '2' ) {
		my $file = Kephra::Document::Data::get_file_path();
		if ( $file and not -w $file ) {$ep->SetReadOnly(1)}
		else                          {$ep->SetReadOnly(0)}
		$status = 'protect';
	}
	_set_attr('readonly', $status);
	$status = $ep->GetReadOnly ? 1 : 0;
	_set_attr('editable', $status);
	Kephra::App::TabBar::refresh_current_label()
		if Kephra::App::TabBar::_config()->{info_symbol};
}
sub set_readonly_on      { set_readonly('on') }
sub set_readonly_off     { set_readonly('off') }
sub set_readonly_protect { set_readonly('protect') }

1;
__END__

=head1 NAME

Kephra::Document::Property - external API for document handling

=head1 DESCRIPTION

=over 4

=item syntaxmode

=item codepage

=item readonly

=item tab size and usage

=item end of line marker

=back